Я изучал асинхронное c поведение в JS, и по большей части все шло хорошо. Я понимаю синхронный способ выполнения кода, единственный поток JS и то, как обратные вызовы, такие как внутри setTimeout, будут синхронизироваться API веб-браузера, а затем добавлены в очередь задач.
событие l oop будет постоянно проверять стек вызовов, и только когда он пуст (весь код syn c выполнен), он будет принимать функции, которые были поставлены в очередь в очереди задач. Отправляет их обратно в стек вызовов, и они выполняются.
Это довольно просто и является причиной того, что следующий код:
console.log('start');
setTimeout(() => console.log('timeout'), 0);
console.log('end');
будет выводить start, end, timeout
.
Теперь, когда я начал читать об обещаниях, я понял, что они имеют более высокий приоритет, чем обычный асинхронный c код, такой как тайм-аут, интервал, прослушиватель событий, и вместо этого будут помещены в очередь заданий / очередь микрозадач. Событие l oop сначала установит приоритет этой очереди и выполнит все задания до исчерпания, прежде чем перейти к очереди задач.
Это все еще имеет смысл, и его можно увидеть, запустив:
console.log('start');
setTimeout(() => console.log('timeout'), 0);
Promise.resolve().then(() => console.log('promise'));
console.log('end');
Это выводит start, end, promise, timeout
. Выполняется синхронный код, обратный вызов then
помещается в стек из очереди микрозадач и выполняется, задача обратного вызова setTimeout из очереди задач отправляется и выполняется. Пока все хорошо.
Я могу осмыслить приведенный выше пример, в котором обещание выполняется немедленно и синхронно, как указано в официальной документации. То же самое произойдет, если мы создадим обещание с ключевым словом new и предоставим функцию исполнителя. Эта функция-исполнитель будет выполняться синхронно и разрешить функцию. Таким образом, когда встречается then, он может просто работать асинхронно на разрешенном обещании.
console.log('start');
const p1 = new Promise(resolve => {
console.log('promise 1 log');
resolve('promise 1');
});
p1.then(msg => console.log(msg));
console.log('end');
Приведенный выше фрагмент выведет start, promise 1 log, end, promise 1
, доказывающее, что исполнитель работает синхронно.
И вот где я запутался с обещаниями, допустим, у нас есть следующий код:
console.log('start');
const p1 = new Promise(resolve => {
console.log('promise 1 log');
setTimeout(() => {
resolve('promise 1');
}, 0);
});
p1.then(msg => console.log(msg));
console.log('end');
Это приведет к start, promise 1 log, end, promise 1
. Если функция исполнителя запускается сразу, это означает, что setTimeout внутри нее будет помещен в очередь задач для последующего выполнения. Насколько я понимаю, это означает, что обещание еще не выполнено. Мы переходим к методу then
и обратному вызову внутри него. Он будет помещен в очередь заданий. остальная часть синхронного кода выполняется, и теперь у нас есть пустой стек вызовов.
Насколько я понимаю, обратный вызов обещания теперь будет иметь приоритет, но как он может выполняться с еще нерешенным обещанием? Обещание должно разрешиться только после того, как будет выполнен setTimeout внутри него, который все еще находится в очереди задач. Я слышал, без каких-либо дополнительных разъяснений, что тогда он будет работать только в том случае, если обещание будет выполнено, и из моего вывода я вижу, что это правда, но я не понимаю, как это будет работать в этом случае. Единственное, что я могу придумать, - это исключение или что-то подобное, и задача очереди задач получает приоритет перед микрозадачей.
Это оказалось долгим, поэтому я благодарен всем, кто нашел время, чтобы прочитать и ответить на это. Я хотел бы лучше понять очередь задач, очередь заданий и событие l oop, поэтому не стесняйтесь размещать подробный ответ! Заранее спасибо.