Javascript.RU

Создать новую тему Ответ
 
Опции темы Искать в теме
  #1 (permalink)  
Старый 27.09.2021, 14:45
Интересующийся
Отправить личное сообщение для Himmelin Посмотреть профиль Найти все сообщения от Himmelin
 
Регистрация: 14.01.2019
Сообщений: 27

Задача на Event Loop
Добрый день! Столкнулся с интересной задачей и не знаю как решить.

function one(callback) {
    setTimeout( function() {
        callback("First");
    }, Math.random() * 100);
}

function two(callback) {
    setTimeout( function() {
        callback("Second");
    }, Math.random() * 100);
}

function three(callback) {
    setTimeout( function() {
        callback("Third");
    }, Math.random() * 100);
}

function runCallback(s) {
    console.log(s);
}


Нужно вызвать функции one, two и three в правильной последовательности, чтобы в консоль вывелось A, B и C в нужном порядке. При этом использовать можно все, даже дописывать runCallback, но сами функции менять нельзя.
Ответить с цитированием
  #2 (permalink)  
Старый 27.09.2021, 15:35
Аватар для Aetae
Тлен
Отправить личное сообщение для Aetae Посмотреть профиль Найти все сообщения от Aetae
 
Регистрация: 02.01.2010
Сообщений: 6,491

Эту задачу можно понимать по разному.
В простейшем варианте вы вызываете следующую функцию из runCallback когда закончилась предыдущая.

Но можно и такое изобразить:
function stream(log, ...args) {
  let index = 0;
  const results = new Map();
  const callback = (i, result) => {
    if(i === index) {
      while(true) {
        log(result);
        if(!results.has(++index))
          break;
        result = results.get(index);
        results.delete(index);
      }
    } else {
      results.set(i, result);
    }
  };
  
  args.forEach((func, i) => func(result => callback(i, result)));
}

stream(runCallback, one, two, three)
получив максимальную возможную скорость вызовов.
__________________
29375, 35
Ответить с цитированием
  #3 (permalink)  
Старый 27.09.2021, 15:44
Интересующийся
Отправить личное сообщение для Himmelin Посмотреть профиль Найти все сообщения от Himmelin
 
Регистрация: 14.01.2019
Сообщений: 27

Понял, спасибо!
Ответить с цитированием
  #4 (permalink)  
Старый 27.09.2021, 20:43
Аватар для ksa
ksa ksa вне форума
CacheVar
Отправить личное сообщение для ksa Посмотреть профиль Найти все сообщения от ksa
 
Регистрация: 19.08.2010
Сообщений: 14,121

Предложу решение "в лоб"...

<!DOCTYPE html>
<html>
<head>
<!--
<script src='https://code.jquery.com/jquery-latest.min.js'></script>
-->
<style type='text/css'>
</style>
<script>
function one(callback) {
    setTimeout( function() {
        callback("First");
    }, Math.random() * 2000);
}

function two(callback) {
    setTimeout( function() {
        callback("Second");
    }, Math.random() * 2000);
}

function three(callback) {
    setTimeout( function() {
        callback("Third");
    }, Math.random() * 2000);
}

function runCallback(s) {
    const o = document.createElement('p')
	o.textContent = s
	document.querySelector('body').appendChild(o)
}

// Вот собственно решение...
const test1 = res => {
	runCallback(res)
	three(runCallback)
}
const test2 = res => {
	runCallback(res)
	two(test1)
}
one(test2)

</script>
</head>
<body> 

</body>
</html>
Ответить с цитированием
  #5 (permalink)  
Старый 27.09.2021, 20:48
Аватар для ksa
ksa ksa вне форума
CacheVar
Отправить личное сообщение для ksa Посмотреть профиль Найти все сообщения от ksa
 
Регистрация: 19.08.2010
Сообщений: 14,121

Или вовсе так...
<!DOCTYPE html>
<html>
<head>
<!--
<script src='https://code.jquery.com/jquery-latest.min.js'></script>
-->
<style type='text/css'>
</style>
<script>
function one(callback) {
    setTimeout( function() {
        callback("First");
    }, Math.random() * 2000);
}

function two(callback) {
    setTimeout( function() {
        callback("Second");
    }, Math.random() * 2000);
}

function three(callback) {
    setTimeout( function() {
        callback("Third");
    }, Math.random() * 2000);
}

function runCallback(s) {
    const o = document.createElement('p')
	o.textContent = s
	document.querySelector('body').appendChild(o)
}

// Вот собственно решение...
one(res => {
	runCallback(res)
	two(res => {
		runCallback(res)
		three(runCallback)
	})
})

</script>
</head>
<body> 
</body>
</html>
Ответить с цитированием
  #6 (permalink)  
Старый 27.09.2021, 21:34
Аватар для voraa
Профессор
Отправить личное сообщение для voraa Посмотреть профиль Найти все сообщения от voraa
 
Регистрация: 03.02.2020
Сообщений: 2,701

Я считаю предыдущие решения некорректными, т.к. при вызове функций используется другой callback. Не сам runCallback
Предлагаю свое решение
function one(callback) {
    setTimeout( function() {
        callback("First");
    }, Math.random() * 1000);
}
 
function two(callback) {
    setTimeout( function() {
        callback("Second");
    }, Math.random() * 1000);
}
 
function three(callback) {
    setTimeout( function() {
        callback("Third");
    }, Math.random() * 1000);
}
 
function runCallback(s) {
    console.log(s);
}

let console;
function call (...funs) {
    const cl = window.console.log
    let i = 0
    console = {
        log (...args) {
            cl(...args)
            if (i<funs.length) 
                 funs[i++](runCallback)
             else
                 console = window.console;
        }   
    }
    funs[i++](runCallback)
}

call(one, two, three)

Последний раз редактировалось voraa, 27.09.2021 в 21:37.
Ответить с цитированием
  #7 (permalink)  
Старый 27.09.2021, 22:21
Аватар для Alexandroppolus
Профессор
Отправить личное сообщение для Alexandroppolus Посмотреть профиль Найти все сообщения от Alexandroppolus
 
Регистрация: 25.10.2016
Сообщений: 1,005

Сообщение от voraa
Я считаю предыдущие решения некорректными, т.к. при вызове функций используется другой callback. Не сам runCallback
то есть вместо патча runCallback сделать патч console.log - это будет честнее?

имхо, раз уж runCallback и callback у функций не склеены изначально, то между ними и надо втыкать "мидлвар".

А в целом задача решается в одну строку, если не городить велосипеды:
// ----- условие --------------
function one(callback) {
    setTimeout( function() {
        callback("First");
    }, Math.random() * 100);
}

function two(callback) {
    setTimeout( function() {
        callback("Second");
    }, Math.random() * 100);
}

function three(callback) {
    setTimeout( function() {
        callback("Third");
    }, Math.random() * 100);
}

function runCallback(s) {
    console.log(s);
}

// ----- решение --------------
Promise.all([one, two, three].map(f => new Promise(f))).then(r => r.forEach(runCallback));
Ответить с цитированием
  #8 (permalink)  
Старый 28.09.2021, 02:07
Аватар для Aetae
Тлен
Отправить личное сообщение для Aetae Посмотреть профиль Найти все сообщения от Aetae
 
Регистрация: 02.01.2010
Сообщений: 6,491

Alexandroppolus, но вся суть в велосипедах.)
Твоя версия запускает все функции сразу и разом выводит всё когда получены все результаты.
Время первого вывода на экран = Время выполнения самой медленной функции.
Время последнего вывода на экран = Время выполнения самой медленной функции.

Версии voraa и ksa запускают функции и выводят результат по порядку.
Время первого вывода на экран = Время выполнения первой функции.
Время последнего вывода на экран = Сумма времени выполнения всех функций.

Мой велосипед запускает все функции сразу, но выводит по мере исполнения и по порядку.)
Время первого вывода на экран = Время выполнения первой функции.
Время последнего вывода на экран = Время выполнения самой медленной функции.

В худшем случае: если первая функция - самая медленная, то результат будет как у тебя, но это крайний вариант. Примерно так работают async стримы, только там есть ещё ограничение на количество одновременно запущенных потоков, чтоб все ресурсы не съело.)
__________________
29375, 35

Последний раз редактировалось Aetae, 28.09.2021 в 02:19.
Ответить с цитированием
  #9 (permalink)  
Старый 28.09.2021, 09:09
Аватар для Alexandroppolus
Профессор
Отправить личное сообщение для Alexandroppolus Посмотреть профиль Найти все сообщения от Alexandroppolus
 
Регистрация: 25.10.2016
Сообщений: 1,005

Aetae, вариант со стримом прикольный, жизненный. Возможно, так и было в исходном условии, но Himmelin сыграл в испорченный телефон.
Ответить с цитированием
  #10 (permalink)  
Старый 28.09.2021, 09:40
Аватар для рони
Профессор
Отправить личное сообщение для рони Посмотреть профиль Найти все сообщения от рони
 
Регистрация: 27.05.2010
Сообщений: 33,068

Aetae,
ksa,
voraa,
Alexandroppolus,
Ответить с цитированием
Ответ



Опции темы Искать в теме
Искать в теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
как создать event, эмулирующий enter Artanis Events/DOM/Window 7 16.07.2019 06:40
Добавление/Перенос Event в Event FullCalendar CI_NAU Events/DOM/Window 0 08.02.2019 16:32
Игра-квест на JS, помогите разобраться в структуре m_lulu Общие вопросы Javascript 1 29.03.2018 14:02
Как отработает Event loop в этой ситуации? xfg Events/DOM/Window 20 23.09.2016 16:25
event + setTimeout fsingle Events/DOM/Window 2 02.05.2012 09:07