javascript #promise #callback
#javascript #обещание #обратный вызов
Вопрос:
Я знаю, что функция обратного вызова внутри setTimeout()
будет ждать, пока не истечет срок действия подключенного к ней таймера, и он будет помещен в очередь обратного вызова. С другой стороны, обещание, после выполнения или отклонения, получает обратный вызов, помещенный в очередь микрозадач, которая имеет более высокий приоритет.
Мой вопрос в том, какой раз быстрее: a setTimeout
внутри обещания или простой setTimeout
. Если первый больше не помещается в очередь микрозадач, почему setTimeout
сначала выполняется alone, а не наоборот?
setTimeout(() => {
console.log('timeout');
}, 1000);
let promise = new Promise(function(resolve, reject) {
// This is run automatically, let's run resolve after 1 second
setTimeout(() => resolve('promise!'), 1000);
});
promise.then(
(result) => console.log(result),
(err) => console.log(error)
);
// output: timeout -> promise || and not || promise -> timeout
Теперь давайте предположим, что я забыл о задержке в 1 секунду, теперь обещание всегда будет отображаться первым, поскольку обратный вызов, запланированный внутри очереди микрозадач, имеет более высокий приоритет
setTimeout(() => {
console.log('timeout');
}, 0);
let promise = new Promise(function(resolve, reject) {
// This is run automatically, let's run resolve after 1 second
// setTimeout(() => resolve('promise!'), 1000);
resolve('');
});
promise.then(() => {
console.log('promise');
});
Комментарии:
1. Быстрее? Я бы предположил, что нет абсолютно никакой существенной разницы. Вы все равно ждете целую секунду.
2. Разработка приложения вокруг того, как среда выполнения будет планировать асинхронные события, является крайне плохой идеей. У вас нет гарантии, что время ожидания в любом случае будет особенно близко к 1000 миллисекундам.
3. В обоих случаях сначала должна быть выполнена макрозадача. С обещанием макрозадача приводит к постановке в очередь микрозадачи. Но я не уверен, насколько это вообще полезно.
4. Было бы очень полезно, если бы вы описали проблему, которую пытаетесь решить.
5. @VLAZ прав. В первом коде будет два
setTimeout()
вызова в очень быстрой последовательности. Среда выполнения поместит их в очередь таймера. Тот, который был запрошен первым, будет запущен первым, а запрошенный второй будет запущен позже. То, что второйsetTimeout()
вызов находится внутри обратного вызова Promise, не имеет абсолютно никакого значения.
Ответ №1:
setTimeout
реализован таким образом, что он предназначен для выполнения после минимальной заданной задержки, и как только поток браузера свободен для его выполнения. итак, для примера, если вы укажете значение 0 для параметра delay и думаете, что он будет выполняться «немедленно», этого не произойдет. он будет, точнее, выполняться в следующем цикле событий (который является частью модели параллелизма цикла событий, которая отвечает за выполнение кода).
Давайте рассмотрим пример для значения задержки 0.
setTimeout(() => {
console.log('timeout');
}, 0);
let promise = new Promise(function(resolve, reject) {
setTimeout(() => resolve('promise!'), 0);
});
promise.then(
(result) => console.log(result),
(err) => console.log(error)
);
setTimeout
Всегда сначала регистрируется результат, потому что он обязательно будет выполняться в следующем цикле событий.
С setTimeout
другой стороны, в обещании будет 2 цикла событий, пока не будет выполнен журнал консоли (один для разрешения обещания, а другой для обратного вызова в функции setTimeout).
Пожалуйста, прочитайте причину задержек дольше, чем указано — https://developer.mozilla.org/en-US/docs/Web/API/setTimeout#reasons_for_delays_longer_than_specified
Подробнее о цикле событий JS — https://developer.mozilla.org/en-US/docs/Web/JavaScript/EventLoop