Как функции asyn c (например, таймеры) внутри обещания обрабатываются в Javascript? - PullRequest
1 голос
/ 18 июня 2020

Мы знаем, что обещания - это микрозадачи, и они добавляются в очередь микрозадач, а прослушиватели / таймеры событий - это задачи, поэтому они добавляются в очередь задач. Но как насчет слушателей / таймеров событий, если они находятся внутри функции обещания (которая передается при создании конструктора обещания для обещания). В какую очередь они добавляются?

console.log("script start");

var promise = new Promise(function (resolve, reject) {
	setTimeout(function () {
		console.log("setTimeout2");
		resolve();
	}, 0);
});
promise.then(function () {
	console.log("promise2");
});
setTimeout(function () {
	console.log("setTimeout");
}, 0);
console.log("script end");

Здесь «запуск сценария» - это часть основной задачи, поэтому она выполняется / печатается.

Затем функция обратного вызова обещания передается браузеру, обработчик добавляет ее в очередь микрозадач.

then () передает обратный вызов обработчику браузера, и он выполнится после того, как будет выполнено основное обещание.

setTimeout, который находится вне обещания, добавляется в очередь задач.

Печатается «конец сценария».

Теперь есть микрозадача в очереди микрозадач и задача в очереди задач.

Таким образом, микрозадача будет выполнена первой, поскольку они имеют более высокий приоритет, чем задача.

Но внутри задачи есть таймер.

Мы знаем, что таймеры добавляются в очередь задач. Но тут мне кажется, что в очередь микрозадач добавлен таймер. Потому что, если бы он был добавлен в очередь задач, то «setTimeout2» был бы напечатан позже, потому что в очереди задач уже есть задача, которая печатает «setTimeout». Так что же там на самом деле происходит?

1 Ответ

1 голос
/ 18 июня 2020

Нет ничего особенного в том, чтобы быть «в обещании». Единственные функции, которые помещаются в очередь микрозадач, - это обратные вызовы, переданные в then.

Вот что на самом деле происходит:

  1. Выполняется журнал script start
  2. Обещание создано и вызывает обратный вызов исполнителя. Обратный вызов исполнителя вызывает setTimeout, который планирует таймер.
  3. Обещание назначается переменной promise
  4. Вызывается метод then(), который присоединяет обратный вызов выполнения к обещанию
  5. Второй setTimeout вызывается и планирует второй таймер
  6. Выполняется script end журнал

Все это произошло синхронно при выполнении одной задачи. Через некоторое время таймеры срабатывают и (только тогда!) Добавляют свои (макро) задачи в очередь событий таймера. Браузер обрабатывает первый:

  1. Выполняется журнал setTimeout2
  2. Выполняется функция resolve(), которая выполняет обещание и добавляет задания для запуска обратных вызовов выполнения в Очередь микрозадач

После выполнения этой макрозадачи выполняются задачи в очереди микрозадач:

  1. Выполняется журнал promise2

Поскольку очередь микрозадач уже пуста, можно выполнить следующую макрозадачу:

  1. Выполняется журнал setTimeout
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...