Первая функция создает объект Promise, но не вызывает его, пока мы не вызовем функцию.Для сравнения, второй оператор создает объект Promise и вызывает его немедленно.Я прав?
Первая функция - это просто функция.Пока это не называется, обещание не создается.Как только он вызван, нет особой разницы с прямым исполнением, которое вы указали в качестве альтернативы.
Я думаю, что когда мы вызываем функцию тайм-аута, она сначала создает асинхронную функцию setTimeout * 1008.*
setTimeout
не создан, функция существует как встроенная функция.Вы можете сказать, что это называется .
... и толкает его в конец очереди событий.
Не сама функция setTimeout
помещается в очередь.Это обратный вызов (resolve
в данном случае), включая аргументы, период ожидания и уникальный идентификатор таймера, который заносится в список активных таймеров.
После завершения всех синхронных событий он будетвызывается и создает объект Promise.
Объект Promise создается во время вызова функции timeout
.
Обратный вызов, который передается на new Promise
, обычно называется обратным вызовом конструктора обещаний , именно в момент выполнения new Promise
выполняется также этот обратный вызов (синхронно) иобещание создано.
Когда синхронный код завершен, то есть, когда стек вызовов пуст, очередь микрозадачи расходуется первой.На этом этапе ничего нет, поэтому очередь задач проверяется.Если к тому времени истек срок действия активного таймера, в очереди задач появится запись о нем.
Объект Promise также будет помещен в конец очереди событий, которая следует за другимисинхронные события
Объект обещания не помещается ни в одну очередь.Когда таймер истекает, событие в очереди будет вызвано как новая задача, то есть будет вызвана функция resolve
, которая, в свою очередь, разрешит обещание, которое, в свою очередь, будет помещать записи в очередь для микрозадач, по одной для каждойthen
обратный вызов и await
связанный эффект.Очередь микрозадач будет обрабатываться в рамках одной и той же (макро) задачи, прежде чем любые другие задачи будут извлечены из очереди.
Так что, похоже, есть два цикла событий, я прав?
Как минимум два;может быть больше.Например, в контексте браузера может быть еще одна очередь для событий, касающихся мутации элемента DOM.См. Также этот ответ о том, что об этом говорят различные спецификации.
Являются ли эти два утверждения равными?
Практически да;Promise.resolve()
- это сокращение от new Promise(r => r())
Почему выходная последовательность похожа на следующую?
setTimeout
включает очередь задач, тогда как .then
включаеточередь микрозадач, которая всегда используется перед обработкой очереди задач;по крайней мере, это консенсус в текущих реализациях.
Приложение
Вот некоторые пояснения к последовательности событий следующего кода:
function timeout(ms){
return new Promise((resolve, reject) => {
setTimeout(resolve, ms, 'done');
});
}
timeout(100).then((value) => {
console.log(value);
});
Сначала кодпроанализировали и создали задачу для ее выполнения:
Задача 1
- Определяется функция
timeout
(переменная поднятая с функцией в качестве значения) timeout
вызывается с аргументом 100 - Объект обещания создается, и обратный вызов конструктора вызывается синхронно.Два аргумента предоставляются системой.Они являются внутренними функциями, которые мы можем вызывать, когда обещание должно перейти в выполненное или отклоненное состояние (это мы должны решить).
setTimeout
вызывается. - Аргументы, переданные в
setTimeout
, используются для создания записи во внутреннем списке таймеров. - Идентификатор таймера возвращается, но ваш код не использует возвращаемое значение.
- Созданный объект обещания возвращается вызывающей стороне
timeout
- Вызывающий объект вызывает метод
then
этого обещания, передавая ему какую-либо функцию (функцию с console.log
) - Внутренняя реализация обещания сохраняет эту функцию в очереди (не очереди событий)для возможного последующего выполнения
- Достигнут конец кода, стек вызовов пуст
- Очередь микро-задач проверяется на наличие любых записей, но она также пуста
В фоновом режиме:
- Время таймера истекает, и запись помещается в очередь задач.Это ожидающий вызов функции, которая была передана в
setTimeout
, т.е. в нашем случае resolve
.Как именно это происходит, зависит от реализации.Суть в том, что в какой-то момент очередь задач имеет эту задачу, которую можно использовать.
Задача 2
- Запись в очереди задач (для вызова
resolve
) найдена и обработана resolve
называется - Внутренние объекты обещания (в которых реализована эта
resolve
функция) помечают обещание как разрешенное - Внутренние элементы обещания создают записи в очереди микрозаданий: по одной для каждого обратного вызова
then
(или await
)он сохранил в своей внутренней очереди.В этом случае есть только одна такая запись: анонимная функция, которая была передана единственному методу then
в коде. - Стек вызовов пуст (это был только вызов
resolve
) - Микро-очередь задач проверяется на наличие любых записей, и есть одна:
Задача 2, Микро-задача 1
- Одна запись в микро-задачеочередь задач потребляется
- анонимная функция называется
console.log
выполняется - Реализация
console
выдает вывод - стек вызовов пуст
- Нет больше записей в очереди микро задач
Больше нет записей в очереди задач.Система продолжает проверять наличие новых записей в очереди задач.