27.09.2021, 14:45
|
Аспирант
|
|
Регистрация: 14.01.2019
Сообщений: 31
|
|
Задача на 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, но сами функции менять нельзя.
|
|
27.09.2021, 15:35
|
|
Тлен
|
|
Регистрация: 02.01.2010
Сообщений: 6,585
|
|
Эту задачу можно понимать по разному.
В простейшем варианте вы вызываете следующую функцию из 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
|
|
27.09.2021, 15:44
|
Аспирант
|
|
Регистрация: 14.01.2019
Сообщений: 31
|
|
Понял, спасибо!
|
|
27.09.2021, 20:43
|
|
CacheVar
|
|
Регистрация: 19.08.2010
Сообщений: 14,215
|
|
Предложу решение "в лоб"...
<!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>
|
|
27.09.2021, 20:48
|
|
CacheVar
|
|
Регистрация: 19.08.2010
Сообщений: 14,215
|
|
Или вовсе так...
<!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>
|
|
27.09.2021, 21:34
|
|
Профессор
|
|
Регистрация: 03.02.2020
Сообщений: 2,745
|
|
Я считаю предыдущие решения некорректными, т.к. при вызове функций используется другой 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.
|
|
27.09.2021, 22:21
|
|
Профессор
|
|
Регистрация: 25.10.2016
Сообщений: 1,012
|
|
Сообщение от 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));
|
|
28.09.2021, 02:07
|
|
Тлен
|
|
Регистрация: 02.01.2010
Сообщений: 6,585
|
|
Alexandroppolus, но вся суть в велосипедах.)
Твоя версия запускает все функции сразу и разом выводит всё когда получены все результаты.
Время первого вывода на экран = Время выполнения самой медленной функции.
Время последнего вывода на экран = Время выполнения самой медленной функции.
Версии voraa и ksa запускают функции и выводят результат по порядку.
Время первого вывода на экран = Время выполнения первой функции.
Время последнего вывода на экран = Сумма времени выполнения всех функций.
Мой велосипед запускает все функции сразу, но выводит по мере исполнения и по порядку.)
Время первого вывода на экран = Время выполнения первой функции.
Время последнего вывода на экран = Время выполнения самой медленной функции.
В худшем случае: если первая функция - самая медленная, то результат будет как у тебя, но это крайний вариант. Примерно так работают async стримы, только там есть ещё ограничение на количество одновременно запущенных потоков, чтоб все ресурсы не съело.)
__________________
29375, 35
Последний раз редактировалось Aetae, 28.09.2021 в 02:19.
|
|
28.09.2021, 09:09
|
|
Профессор
|
|
Регистрация: 25.10.2016
Сообщений: 1,012
|
|
Aetae, вариант со стримом прикольный, жизненный. Возможно, так и было в исходном условии, но Himmelin сыграл в испорченный телефон.
|
|
28.09.2021, 09:40
|
|
Профессор
|
|
Регистрация: 27.05.2010
Сообщений: 33,109
|
|
Aetae,
ksa,
voraa,
Alexandroppolus,
|
|
|
|