Сегодня я написал письменный тестовый вопрос, которым я считаю очень важным поделиться с вами. Тема следующая:
setTimeout(()=>{
console.log('A');
},0);
var obj={
func:function () {
setTimeout(function () {
console.log('B')
},0);
return new Promise(function (resolve) {
console.log('C');
resolve();
})
}
};
obj.func().then(function () {
console.log('D')
});
console.log('E');
JavaScript знает, что это однопоточный язык, а это значит, что JS не может выполнять многопоточное программирование, но у JS есть вездесущиеасинхронныйконцепция . Чтобы полностью понять асинхронность, вам нужно понять ядро JS —цикл событий.
1. Что такое очередь событий?
Первый взгляд на небольшую демонстрацию
console.log('start');
setTimeout(()=>{
console.log('A');
},1000);
console.log('end');
//start
//end
//A
После выполнения js программа выводит «начало» и «конец», а «A» выводится примерно через 1 с. Итак, у нас есть вопросы? Почему A не выполняется до конца?
Это связано с тем, что setTimeout является асинхронной функцией. Это означает, что когда мы устанавливаем функцию задержки, текущий скрипт не будет блокироваться, он просто запишется в таблицу событий браузера, а программа продолжит выполнение вниз. Когда время задержки истечет, таблица событий добавит функцию обратного вызова вочередь событий (очередь задач), после того как очередь событий получает задачу, она помещает задачу вСтек выполнения (стек)Среди них стек выполнения выполняет задачу и выводит «A».
очередь событийпредставляет собой очередь, в которой хранятся задачи для выполнения, причем задачи строго в соответствии схронологический порядокВыполнено, задача в начале очереди будет выполнена первой, а задача в конце очереди будет выполнена последней. Очередь событий выполняет только одну задачу за раз, и после выполнения задачи выполняется следующая задача. Стек выполнения — это работающий контейнер, аналогичный стеку вызовов функций. Когда стек выполнения пуст, механизм JS проверяет очередь событий. Если она не пуста, очередь событий помещает первую задачу в стек выполнения для запуска.
Затем я внесу небольшое изменение в этот пример и посмотрю:
console.log('start');
setTimeout(()=>{
console.log('A');
},0);
console.log('end');
//start
//end
//A
Видно, что после того, как мы установили второй параметр settimeout в 0, «A» всегда будет выводиться после «end». Так что именно произошло? Это связано с тем, что обратный вызов для setTimeout просто добавлен вочередь событий, вместо немедленного выполнения. Поскольку текущая задача не была выполнена, задача setTimeout не будет выполнена. После вывода «end» текущая задача выполняется, а стек выполнения пуст. В это время очередь событий поместит функцию обратного вызова setTimeout в стек выполнения для выполнения.
2. Каково значение и основное использование Promise?
так называемыйPromise
, который представляет собой просто контейнер, содержащий результат события (обычно асинхронной операции), которое завершится в будущем. Синтаксически Promise — это объект, из которого можно получить сообщение для асинхронной операции. Обещания предоставляют унифицированный API, и различные асинхронные операции могут обрабатываться одинаково.
Напишите небольшое демо, чтобы увидеть рабочий механизм Promise:
let promise = new Promise(function(resolve, reject) {
console.log('Promise');
resolve();
});
promise.then(function() {
console.log('resolved.');
});
console.log('Hi!');
// Promise
// Hi!
// resolved
В приведенном выше коде после создания Promiseвыполнить немедленно, поэтому первый выводPromise
. Потом,then
Функция обратного вызова, указанная методом, будет выполнена в текущем скрипте.Выполняется после выполнения всех задач синхронизации,такresolved
Окончательный вывод.
три,Макрозадачи и микрозадачи
И макрозадачи, и микрозадачи относятся к одной из указанных выше асинхронных задач и имеют следующие API:
macrotasks: setTimeout, setInterval, setImmediate, I/O, UI rendering
microtasks: process.nextTick, Promise, MutationObserver
В чем разница между макрозадачей setTimeout и микрозадачей Promise?Давайте сначала посмотрим на код следующим образом:
console.log(1);
setTimeout(function(){
console.log(2);
}, 0);
Promise.resolve().then(function(){
console.log(3);
}).then(function(){
console.log(4);
});
//1
//3
//4
//2
Как видно из приведенного выше кода,PromiseКод функции асинхронной задачи будетприоритетВsetTimeoutЗадачи с задержкой 0 выполняются первыми.
Причина в том, что очередь задач разделена на макрозадачи и микрозадачи, и функция метода then в промисе будет запушена в очередь микрозадач, а функция setTimeout будет запушена в макрозадачи
В очереди задач, в каждом цикле событий,macrotaskТолькоизвлечь казнь,иmicrotaskвстречаВсегдавыборка до очереди MicrosoftПустодо того как.
Другими словами, если задача микрозадачи запущена в выполнение, то при выполнении задачи основного потока следующая задача в очереди будет циклически вызываться для выполнения до тех пор, пока очередь задач не достигнет последней задачи.
Цикл событий будет помещать в стек только одну макрозадачу за раз,основной потокПосле выполнения задачи снова проверитmicrotasksСтавьте в очередь и выполняйте все задачи в ней перед выполнениемmacrotaskзадача.
В-четвертых, проанализируйте эту тему
setTimeout(()=>{
console.log('A');
},0);
var obj={
func:function () {
setTimeout(function () {
console.log('B')
},0);
return new Promise(function (resolve) {
console.log('C');
resolve();
})
}
};
obj.func().then(function () {
console.log('D')
});
console.log('E');
1. ПервыйsetTimeout А добавляется кочередь событийв ==> в это времяmacrotasksимеет'];
2. Когда выполняется obj.func(), setTimeout B добавляется кочередь событийв ==> в это времяmacrotasksимеет ['A', 'B'];
3. Затем верните объект Promise после нового создания Promise.выполнить немедленноВыполнить console.log('C');первыйнапечатать «С»;
4. Затемthen
Функция обратного вызова, указанная методом, добавляется вmicrotasksОчередь будет выполняться после выполнения всех задач синхронизации текущего скрипта. ==> в это времяmicrotasksимеет ['D'];
5. Затем продолжайте выполнять задачу синхронизации текущего скрипта, поэтому консоль сначалавторичныйвывод «Е»;
6. На этом все задачи синхронизации завершены, сначала проверьте, как указано выше.microtasksочередь,Выполните все эти задания, поэтому сначала консольтри разавыход «Д»;
7. Наконец выполнитьmacrotaskзадач, а в соответствии с хронологическим порядком очереди консоль перваячетыре разаВывод 'A', сначала консольв пять разВыход «Б».
5. Выполнить js-код
Анализ соответствует действительности, КРАСИВО!
Справочная статья:блог woo woo woo.cn на.com/Tugenhua070…
Есть также введение обещания г-на Жуана:Умер от голода 6. Жуань Ифэн.com/?search=pro…
Статья оригинальна, пожалуйста, прокомментируйте, если она перепечатана;
Новички во фронтенде все еще имеют много недостатков в понимании JavaScript, если есть какие-то ошибки, вы можете указать на них;
Если вам понравилось, ставьте палец вверх!