setTimeout
1. Первоначальный вид setTimeout
定义:setTimeout() 方法用于在指定的毫秒数后调用函数或计算表达式。
грамматика:
setTimeout(code, milliseconds, param1, param2, ...)
setTimeout(function, milliseconds, param1, param2, ...)
параметр | описывать |
---|---|
code/function | Необходимый. Для вызова строки кода, которая также может быть функцией |
milliseconds | Необязательный. Количество времени в миллисекундах, необходимое для ожидания выполнения или вызова кода/функции. По умолчанию 0. |
param1, param2, ... | Необязательный. Дополнительные аргументы, передаваемые функции execute (не поддерживаются в IE9 и более ранних версиях). |
Во-вторых, установите время первого знакомства
Первый
setTimeout(fn1, 1000);
setTimeout(fn2, 2000);
setTimeout(function fn3(){console.log(3);}, 3000);
setTimeout(function (){console.log(4);}, 4000);
function fn1(){
console.log(1);
}
var fn2 = function(){
console.log(2);
}
//输出结果如下:
// 分别延迟1,2,3,4秒之后输出 1 2 3 4
второй
setTimeout(fn1(), 1000);
setTimeout(fn2(), 2000);
setTimeout(function fn3(){console.log(3);}(), 3000);
setTimeout(function (){console.log(4);}(), 4000);
function fn1(){
console.log(1);
}
var fn2 = function(){
console.log(2);
}
//输出结果如下:
//直接输出 1 2 3 4 ,没有延迟
По определению: метод setTimeout() используется для вызова функции или вычисления выражения по прошествии заданного количества миллисекунд. Первый метод выполняется через указанное количество миллисекунд, второй метод выполняется не через указанное количество миллисекунд, а сразу. Так что лично я делю на обычный армейский setTimeout и небрендовый армейский setTimeout, что удобно для последующего запоминания.
О регулярной армии подробнее поговорим позже, а теперь давайте разберемся с пестрой армией: Поскольку первый параметр setTimeout() равеннепосредственно исполняемый код, поэтому он не имеет эффекта задержки, а именно:
setTimeout(console.log(1), 1000);
//输出结果如下:
//直接输出 1 ,没有延迟
Три, setTimeout встретиться снова
setTimeout(function(a,b){
console.log(a+b);
},1000,4,5);
//输出结果如下:
//9
Начиная с третьего параметра, он по очереди используется для представления параметров, переданных первым параметром (функция обратного вызова). Некоторые старые браузеры не поддерживают ее, вы можете использовать метод bind или apply для ее решения следующим образом:
setTimeout(function(a,b){
console.log(a+b);
}.bind(this,4,5),1000);
//输出结果如下:
//9
Первый параметр указывает, что this исходной функции привязан к глобальной области видимости, а второй параметр начинается с параметров, которые необходимо передать в исходную функцию. Когда функция связывания вызывается, функция связывания будет использовать первый параметр, переданный методу связывания (), когда он был создан, как это
В-четвертых, setTimeout знают друг друга
По этой проблеме с setTimeout() в Интернете есть много статей, поэтому я не буду пытаться что-то с этим делать.Если резюме будет на месте, я напишу статью, чтобы представить ее.
console.log(1);
setTimeout(function (){
console.log(2);
},3000);
console.log(3);
//输出结果如下:
//1 3 2
console.log(1);
setTimeout(function (){
console.log(2);
},0);
console.log(3);
//输出结果如下:
//1 3 2
Некоторые студенты могут быть сбиты с толку: вывод 1, 3 и 2 после задержки первого кода на три секунды — это понятно, но почему второй код выводит 1, 3 и 2 после задержки в 0 секунд?
Здесь нужно упомянуть о понятии «очередь задач», потому что JavaScript — это однопоточный язык, а это значит, что одновременно может выполняться только одно действие. Но HTML5 предлагает стандарт Web Worker, который позволяет сценариям JavaScript создавать несколько потоков, но подпотоки полностью контролируются основным потоком. Однопоточный означает, что все задачи должны быть поставлены в очередь, а следующая задача будет выполняться после завершения предыдущей задачи. Если предыдущая задача занимает много времени, последняя задача должна ждать вечно.
Итак, дизайнер делит задачу на два типа, одинСинхронизировать задачу, другойасинхронная задача. Синхронная задача — это задача, поставленная в очередь на выполнение в основном потоке, причем последняя может быть выполнена только после выполнения предыдущей; Асинхронная задача — это задача, которая не входит в основной поток, а входит в «очередь задач».Только когда «очередь задач» сообщает основному потоку, что асинхронная задача может быть выполнена, задача попадает в основной поток для выполнения.
В дополнение к размещению событий задачи «очередь задач» также может размещать события, рассчитанные по времени. То есть указать, сколько времени после выполнения определенного кода. Зная это, мы можем объяснить, почему приведенные выше два фрагмента кода выдают такие результаты.
Первый фрагмент кода, потому что setTimeout() задерживает выполнение функции обратного вызова через 3000 миллисекунд. Если второй параметр setTimeout() установлен в 0, это означает, что указанная функция обратного вызова (интервал 0 миллисекунд) будет выполнена сразу после выполнения текущего кода. Таким образом, только после того, как будут напечатаны 1 и 3, система выполнит функцию обратного вызова в «очереди задач».
Короче говоря, смысл setTimeout(fn,0) состоит в том, чтобы указать, что задача выполняется в самое раннее доступное время простоя основного потока, то есть как можно раньше. Он добавляет событие в конец «очереди задач», поэтому оно не будет выполнено до тех пор, пока не будут обработаны как задача синхронизации, так и существующие события «очереди задач». Подчеркнем еще раз: он добавляет событие в хвост «очереди задач», помните, что это хвост, добавленный в хвост «очереди задач», поэтому он выполняется последним.
Стандарт HTML5 определяет минимальное значение (кратчайший интервал) второго параметра setTimeout(), которое не должно быть меньше 4 миллисекунд, если оно меньше этого значения, оно будет автоматически увеличиваться. До этого старые браузеры устанавливали минимальный интервал в 10 миллисекунд.
setTimeout() просто вставляет событие в «очередь задач» и должен дождаться выполнения текущего кода (стека выполнения), прежде чем основной поток выполнит указанную им функцию обратного вызова. Если текущий код занимает много времени, это может занять много времени, поэтому нет способа гарантировать, что функция обратного вызова будет выполнена во время, указанное setTimeout(). Поэтому они не всегда могут быть вовремя. Пунктуальность - хороший мальчик!
Учитель Руан Ифэн подробно рассказал об очереди задач.кликните сюда
Пять, setTimeout знакомый
Разобравшись с вышеуказанным содержанием, мы должны вытащить его и сразу перейти к тестовым вопросам:
console.log(1);
setTimeout(fn1, 1000);
setTimeout(function(){
console.log(2);
},0);
setTimeout(console.log(3),2000);
function fn1(){
console.log(4);
}
console.log(5);
//输出结果:
//1 3 5 2 4(4会延迟一秒)
1. Сначала запустите основной поток и распечатайте 1;
2. Когда встречается первый setTimeout, функция обратного вызова выполняется через 1 секунду, поэтому она добавляется в очередь задач;
3. Когда встречается второй setTimeout, функция обратного вызова выполняется через 0 секунд и снова добавляется в очередь задач;
4. При встрече с третьим setTimeout первый параметр - это не функция обратного вызова, а непосредственно исполняемый оператор.Помните, что этот, о котором я упоминал ранее, - разношерстная команда, он не будет добавлен в очередь задач и не будет задерживать выполнение. , выполняется напрямую, поэтому печатается 3;
5. Продолжайте распечатывать 5;
6. Второй setTimeout, поскольку это 0-секундная задержка, задача основного потока выполняется сразу после окончания, поэтому печатается 2;
7. Наконец, выполните первый setTimeout и выведите 4 через одну секунду.
После понимания приведенных выше тестовых вопросов мы можем понять следующий код:
var timeoutId = setTimeout(function (){
console("hello World");
},1000);
clearTimeout(timeoutId);
//输出结果:
//不会打印出hello World
1. Сначала запустите основной поток, столкнитесь с setTimeout и первым параметром — функцией обратного вызова, добавьте его в очередь задач и выполните через 1 секунду;
2. Если выполняется clearTimeout, таймер будет отменен до того, как код будет выполнен, поэтому ничего не будет напечатано.
Давайте узнаем об обещаниях
promise
1. Первое появление промисов
ES6 записывает обещания в стандарт языка, унифицирует использование и изначально предоставляет объекты Promise. Подробное введениекликните сюдаУчитель Жуань Ифэн дал подробное объяснение;
Здесь я кратко скажу, что я буду использовать позже: Промис будет выполнен сразу после его создания, тогда метод then принимает в качестве параметров две callback-функции, которые будут выполняться после выполнения всех задач синхронизации текущего скрипта. Помните, что функция обратного вызова после этого выполняется асинхронно, поэтому она будет добавлена в очередь задач. Первая функция обратного вызова вызывается, когда состояние объекта Promise становится разрешенным, а вторая функция обратного вызова вызывается, когда состояние объекта Promise становится отклоненным. Среди них вторая функция не является обязательной и не обязательно.
Во-вторых, первое знакомство с обещанием
Далее я постепенно буду видеть различные вопросы интервью, которые появляются в виде фрагментов кода, чтобы углубить ваше понимание.
console.log(1);
new Promise((resolve,reject)=>{
console.log(2);
resolve()
}).then( ()=>{
console.log(3)
},()=>{
console.log(4);
});
console.log(5);
//输出结果:
//1 2 5 3
1. Сначала запустите основной поток и распечатайте 1;
- Обещание будет выполнено сразу после его создания, поэтому выводится 2, а выполнение resolve указывает на то, что выполнение выполнено успешно и вызывается обратный вызов;
- Успешным выполнением then является функция обратного вызова, поэтому она выполняется асинхронно, добавляется в очередь задач и пока не будет выполняться;
- Продолжайте выполнять основной поток, распечатайте 5;
- После завершения основного потока функция обратного вызова в очереди задач выполнения выводит 3
console.log(1);
new Promise((resolve,reject)=>{
console.log(2);
reject()
}).then( ()=>{
console.log(3)
},()=>{
console.log(4);
});
console.log(5);
//输出结果:
//1 2 5 4
Этот пример такой же, как и выше, но выполняется асинхронная неудачная функция обратного вызова, поэтому последняя напечатанная функция равна 4.
console.log(1);
new Promise((resolve,reject)=>{
console.log(2);
}).then( ()=>{
console.log(3)
});
console.log(4);
//输出结果:
//1 2 4
В этом примере 3 не печатается после 4, потому что обещание не указывает, следует ли выполнить успешный обратный вызов или неудачный обратный вызов, поэтому функция обратного вызова then не будет выполнена.
console.log(1);
new Promise((resolve,reject)=>{
console.log(2);
}).then(console.log(3));
console.log(4);
//输出结果:
//1 2 3 4
Некоторые студенты могут быть сбиты с толку, увидев это. В чем дело? Почему 1234 вместо 1243? Необходимо проверить, внимательны ли студенты. Видя, что then в непосредственном является исполняемым оператором, а не функцией обратного вызова, так что это появится.В этом случае асинхронная задача должна быть функцией обратного вызова, если это не функция обратного вызова, она является синхронной
1. Сначала запустите основной поток и распечатайте 1;
- Обещание будет выполнено сразу после его создания, поэтому печатается 2;
- Then — это не функция обратного вызова, а непосредственно исполняемый оператор, поэтому выведите 3 непосредственно при выполнении;
- Продолжайте выполнять основной поток и выведите 4;
Хи-хи, я полагаю, что после прочтения приведенных выше примеров вы уже многое поняли о промисах, поэтому давайте продолжим более подробно рассматривать следующий пример.
console.log(1);
new Promise((resolve,reject)=>{
console.log(2);
resolve();
console.log(3);
}).then( ()=>{
console.log(4)
});
console.log(5);
//输出结果:
//1 2 3 5 4
Вы правильно написали? Вопрос здесь, вероятно, в console.log(3) после resolve(); это место Это связано с тем, что в приведенном выше коде после вызова resolve() последующий файл console.log(3) все еще будет выполняться и будет напечатан первым. Поскольку немедленно разрешенное обещание выполняется в конце текущего раунда цикла событий, оно всегда позже, чем текущий раунд задач синхронизации.
Поэтому, если вы хотите, после вызова разрешения или отклонения миссия Promise завершается, и последующие операции должны быть помещены в метод then, а не непосредственно за разрешением или отклонением. Так что лучше ставить перед ними операторы return, чтобы не было сюрпризов. следующим образом:
console.log(1);
new Promise((resolve,reject)=>{
console.log(2);
return resolve();
console.log(3);
}).then( ()=>{
console.log(4)
});
console.log(5);
//输出结果:
//1 2 5 4
В этом случае console.log(3); не будет выполнен.
3. Обещание и установка времени ожидания
Давайте посмотрим, что произойдет, если promise и setTimeout появятся одновременно? следующим образом:
console.log('a');
setTimeout(function() {console.log('b')}, 0);
new Promise((resolve, reject) => {
for(let i=0; i<10000000; i++) {
if(i==999999) {
console.log('c');
resolve();
}
}
console.log('d');
}).then(() => {
console.log('e');
});
console.log('f');
//输出结果:
// a c d f e b
У вас немного кружится голова, хахаха, не волнуйтесь, здесь мы должны немного расширить новую концепцию, чтобы облегчить наше понимание: цикл событий, макрозадача и микрозадача
Основной особенностью JavaScript является один поток, и этот поток имеет только один цикл обработки событий.
В потоке цикл событий уникален, но в очереди задач их может быть несколько.
Очередь задач далее делится на макрозадачи (macrotask) и микрозадачи (microtask), которые также называются задачами и заданиями.
Макро-задача, вероятно, включает в себя: сценарий (общий код), setTimeout, setInterval, setImmediate, ввод-вывод, рендеринг пользовательского интерфейса.
Микрозадачи, вероятно, включают: process.nextTick, Promise, MutationObserver (новые функции в html5)
Порядок цикла событий определяет порядок выполнения кода JavaScript.
Он запускает первый цикл из скрипта (общий код). Затем глобальный контекст попадает в стек вызовов функций.
Пока стек вызовов не опустеет (остался только глобал), то выполняем все микрозадачи.
После выполнения всех исполняемых микрозадач.
Цикл снова начинается с макрозадачи, находит, что одна из очередей задач выполняется, а затем выполняет все микрозадачи (микрозадачи) и так далее.
Примечание: макрозадача, используемая в этой статье: script (общий код), setTimeout, setInterval; микрозадача (микрозадача): Promise. Что касается других браузеров, то упоминается API node.js, например: setImmediate, process.nextTick и т. д. Что касается их порядка выполнения, см.эта статья
Например, в приведенном выше примере разные типы задач будут поступать в очередь задач своего типа, например, все обратные вызовы setTimeout() будут попадать в очередь задач setTimeout, которая является макрозадачей, а все обратные вызовы then() будут поступать в очередь задач. затем очередь, обе микрозадачи (микрозадачи).
Текущий общий код мы можем рассматривать как задачу макроса. Цикл событий запускает первый цикл событий из текущего общего кода, а затем выполняет все микрозадачи в очереди.Когда микрозадачи выполняются, цикл событий находит одну из очередей макрозадач и выполняет все задачи в ней, а затем находит еще один.Очередь микрозадач и выполняет все задачи в ней, и так далее. Это цикл событий, как я понимаю.
Проанализируйте приведенный выше пример:
1. Сначала выполните весь код, первым распечатайте
2. Когда выполняется первый setTimeout, обнаруживается, что это задача макроса.В это время будет создана новая очередь задач макроса типа setTimeout, и функция обратного вызова текущего setTimeout будет отправлена во вновь созданную задачу макроса. очередь.
3. Выполнить для нового промиса, первый параметр в конструкторе промиса будет выполняться непосредственно, когда он новый, поэтому он не попадет в какую-либо очередь, поэтому третий вывод - c
4. После выполнения resolve() продолжите выполнение в обратном порядке и распечатайте d
5. Как упоминалось выше, Promise.then — это микрозадача, тогда здесь будет сгенерирована очередь микрозадач типа Promise.then, а затем callback здесь будет помещен в эту очередь.
6. Вернитесь и распечатайте f
7. Выполнение макрозадачи первого раунда цикла событий завершено (весь код рассматривается как макрозадача). В настоящее время существует только одна очередь микрозадач типа Promise.then в очереди микрозадач. Также существует только одна очередь задач макросов типа setTimeout в очереди задач макросов.
8. Следующие микрозадачи выполняют первый раунд циклов событий, очевидно, будет напечатано e, и первый раунд циклов событий завершен.
9. Запустите второй раунд цикла обработки событий: выполните все задачи в очереди типа setTimeout (очередь задач макросов), есть только одна задача, поэтому распечатайте b
10. Заканчивается макрозадача второго раунда событий, завершается цикл событий.
Еще один супер пример, где у вас есть я, а у меня есть вы, испытайте тестовые вопросы, полные ям, хе-хе ;-)
console.log('a');
setTimeout(function () {
console.log('b')
new Promise(resolve=> {
console.log('c')
resolve()
}).then(()=> {
console.log('d')
})
},2000);
new Promise((resolve,reject)=>{
console.log('e');
resolve();
console.log('f');
}).then(()=>{
console.log('g')
});
console.log('h');
new Promise((resolve,reject)=>{
setTimeout(function () {
console.log('i');
},0);
}).then(console.log('j'));
setTimeout(function () {
console.log('k')
new Promise(resolve=>{
console.log('l')
return resolve()
console.log('m')
}).then(()=>{
console.log('n')
})
},1000);
console.log('p');
//输出结果:
//a e f h j p g i
//延迟1s 输出:k l n
//再延迟1s 输出:b c d
1. Сначала выполните общий код, первый выводит «а»;
2. Когда выполняется первый setTimeout, обнаруживается, что это задача макроса.В это время будет создана новая очередь задач макроса типа setTimeout, и функция обратного вызова текущего setTimeout будет отправлена во вновь созданную задачу макроса. очередь и ее очередь. Когда она выполняется, она будет выполнена с задержкой в 2 секунды;
3. Выполнить для первого нового промиса, первый параметр в конструкторе промиса будет выполняться непосредственно, когда он новый, поэтому он не попадет в какую-либо очередь, поэтому вторым выходом будет «e», оператор после resolve() будет продолжать выполняться , поэтому третий вывод — «f», Promise.then — это микрозадача, затем здесь будет сгенерирована очередь микрозадач типа Promise.then, а затем в эту очередь будет помещен обратный вызов then здесь;
4. Выполните общий код еще раз, и четвертый выведет «h»;
5. Когда выполняется первый новый промис, первый параметр в конструкторе промиса будет выполняться непосредственно, когда он новый, но это setTimeout, выясняется, что это макрозадача, и его обратный вызов отправляется в указанный выше тип setTimeout. задачи макроса ставятся в очередь. Следующий Promise.then является исполняемым кодом, а не функцией обратного вызова, поэтому он будет выполнен напрямую и не будет добавлен в микрозадачу, поэтому пятый вывод: "j";
6. При выполнении второго setTimeout обнаруживается, что это задача макроса, и его обратный вызов отправляется в очередь задач макроса вышеуказанного типа setTimeout, но выполнение будет задержано на 1с;
7. Выполнить общий код, шестой вывод "p";
8. Выполнение макрозадачи первого раунда цикла событий завершено (весь код рассматривается как макрозадача). В настоящее время существует только одна очередь микрозадач типа Promise.then в очереди микрозадач, в которой есть задача, а также только одна очередь макрозадач типа setTimeout в очереди макрозадач;
9. Следующие микрозадачи выполняют первый раунд цикла событий Очевидно, что седьмой выход: "g". На этом первый раунд цикла событий завершен;
10. Запустить второй раунд событийного цикла: выполнить все задачи в очереди типа setTimeout (очередь макрозадач). Обнаружено, что у некоторых есть задержки, а у некоторых нет задержек, поэтому макрозадачи с наименьшей задержкой выполняются первыми;
11. Выполнить setTimeout, восьмой вывод "i";
12. Затем выполните setTimeout с задержкой в 1 с, поэтому девятый вывод после задержки в одну секунду: "k";
13. После обнаружения нового промиса первый параметр в конструкторе промиса будет выполняться непосредственно, когда он новый, поэтому он не попадет в какую-либо очередь, поэтому десятый вывод — «l», за которым следует оператор возврата, поэтому следующий код будет не выполняться, и "m" не будет выведено;
14. Но здесь находится then, и оно помещается в очередь then, которая была выполнена выше.Здесь следует отметить, что, поскольку есть микрозадача then очереди, все задачи в очереди будут выполняться здесь (в на этот раз только задача), так что одиннадцатый выход — «n»;
15. Выполнить setTimeout с задержкой в 1 с, поэтому двенадцатый вывод после задержки в две секунды: "b";
16. После обнаружения нового промиса первый параметр в конструкторе промиса будет выполняться непосредственно, когда он новый, поэтому он не попадет в какую-либо очередь, поэтому тринадцатый вывод — «c»;
17. Но снова найдено then, и оно проталкивается в очередь then, которая была выполнена выше.Здесь следует отметить, что поскольку существует микрозадача then очереди, все задачи в очереди будут выполняться здесь (в на этот раз только одна задача), так что четырнадцатый результат — «d»;
Пфф, наконец-то это закончилось, не знаю, все ли это понимают? Такова жизнь. Ты думаешь, что после трудного времени перед тобой Солнечная аллея, но реальность такова. Он даст тебе другую проблему. Тогда посмотри на код ниже, хе-хе-хе~~~
async function async1() {
console.log("a");
await async2();
console.log("b");
}
async function async2() {
console.log( 'c');
}
console.log("d");
setTimeout(function () {
console.log("e");
},0);
async1();
new Promise(function (resolve) {
console.log("x");
resolve();
}).then(function () {
console.log("y");
});
console.log('z');
//输出结果:
// d a c x z y b e
Разве это не глупо, почему снова появляется асинхронность, не паникуйте, не паникуйте и слушайте меня медленно, прежде чем я это скажу, каждый должен знать об асинхронности, у г-на Руан Ифэн есть подробное введение в это, подробностикликните сюда
Async
1. асинхронный
Использование async, которое помещается перед функцией в качестве ключевого слова, используется для указания того, что функция является асинхронной функцией, поскольку async означает асинхронную, а асинхронная функция означает, что выполнение функции не будет блокировать выполнение следующий код.
Давайте сначала посмотрим на возвращаемое значение async, см. следующий код:
async function testAsync() {
return "hello async";
}
const result = testAsync();
console.log(result);
//输出结果:
// Promise { 'hello async' }
Увидев это, мы знаем, что вывод saync является объектом обещания.
Асинхронные функции (включая операторы функций и функциональные выражения) будут возвращать объект Promise.Если в функции возвращается прямое количество, асинхронное инкапсулирует прямое количество в объект Promise с помощью Promise.resolve().
Так что, если мы попытаемся не иметь возвращаемого значения?
async function testAsync() {
console.log("hello async");
}
const result = testAsync();
console.log(result);
//输出结果:
// hello async
// Promise { undefined }
вернет пустой объект обещания
2. ждать
Буквально await означает ожидание, await ожидает выражение, и возвращаемое значение этого выражения может быть объектом-обещанием или другими значениями.
Обратите внимание, что await используется не только для ожидания объектов Promise, но и для ожидания результата любого выражения, так что после await могут следовать обычные вызовы функций или прямые количества.
function getSomething() {
return "something";
}
async function testAsync() {
return Promise.resolve("hello async");
}
async function test() {
const v1 = await getSomething();
const v2 = await testAsync();
console.log(v1, v2);
}
test();
//输出结果:
// something hello async
await – это оператор, используемый для формирования выражений.Результат выражения await зависит от того, чего он ожидает.Если то, чего он ждет, не является объектом Promise, то результатом ожидания будет то, чего он ждет.
содержание | описывать |
---|---|
грамматика | [return_value] = await expression; |
выражение | Объект Promise или любое значение для ожидания. |
возвращаемое значение (return_value) | Возвращает результат обработки объекта Promise. Если ожидаемый объект не является объектом Promise, возвращается само значение |
Но как он будет выполнен, когда встретит await?
Асинхронную функцию можно рассматривать как несколько асинхронных операций, упакованных в объект Promise, а команда await является синтаксическим сахаром для внутренней команды then. Когда функция выполняется, как только она встретит await, она сначала вернется, дождется завершения асинхронной операции, а затем выполнит оператор, стоящий за телом функции.
который,
При встрече с телом асинхронной функцииawait test();
Когда выполните test(), а затем получите значение возвращаемого значения (может быть обещанием или другим значением), состоящее изawait value;
, Если значение является объектом обещания, возвращенное обещание будет помещено в очередь задач для ожидания, ожидание выпустит поток, выпрыгнет из асинхронной функции и продолжит выполнение последующего кода; если значение равно другим значениям , он не будет добавлен в очередь. Это просто очередь задач, await также выдаст поток, выпрыгнет из асинхронной функции и продолжит выполнение последующего кода.
Зная это, давайте проанализируем самую сложную часть кода выше:
1. Сначала выполните весь код, встретите две функции saync, они не вызываются, поэтому продолжайте выполнение вниз, поэтому первый вывод: «d»;
2. Когда выполняется первый setTimeout, обнаруживается, что это задача макроса.В это время будет создана новая очередь задач макроса типа setTimeout, и функция обратного вызова текущего setTimeout будет отправлена во вновь созданную задачу макроса. очередь, и ее очередь выполняется сразу же при ее выполнении;
3. Когда встречается async1(), вызывается функция async1, выполняется функция async1, и второй вывод: "a";
4. Затем выполните await async2() и обнаружите, что async2 также является функцией, определенной async, поэтому «console.log('c')» выполняется напрямую. Итак, третий вывод: "c";
5. При этом async2 возвращает промис, обратите внимание: возвращенный в это время промис будет поставлен в очередь задач на ожидание, ожидание выпустит поток, а затем функция async1 выскочит и продолжит выполнение ! ! !
6. Выполнение нового промиса Как упоминалось ранее, промис выполняется немедленно, поэтому четвертый вывод: "x";
7. Затем, когда выполняется разрешение, задача разрешения помещается в очередь задач для ожидания, а затем выпрыгивает из промиса и продолжает выполняться, поэтому пятый вывод: «z»;
8. Теперь, когда стек вызовов пуст, цикл событий перейдет в очередь задач, чтобы получить задачи и продолжить помещать их в стек вызовов;
9. Первая извлекаемая задача — это промис, поставленный async1.При выполнении промиса он сталкивается с функцией разрешения или отклонения.На этот раз он будет помещен в очередь задач для ожидания, а затем снова выскочит из функции async1. для продолжения следующей задачи. ! ! !
10. Следующей извлекаемой задачей является обратный вызов разрешения, введенный новым промисом, а затем выполняется команда then, поэтому шестой вывод: "y";
11. Стек вызовов снова очищается, и цикл событий получает следующую задачу.Выполняется функция разрешения или отклонения объекта обещания, возвращенного async2 в функции async1.Поскольку async2 ничего не возвращает, параметр этого разрешения неопределенный;
12. В это время обещание, определенное ожиданием, было выполнено, и результат был возвращен, поэтому вы можете продолжить выполнение задачи, стоящей за функцией async1, которая называется «console.log('b')», поэтому седьмой вывод: "б";
13. Стек вызовов снова пуст, и, наконец, выполняется макрозадача setTimeout, поэтому восьмой вывод: «e»
Вот это да(@ο@) Вау~, я решил проблему, вы, ребята, понимаете? Надеюсь, вы больше не будете бояться вопросов на интервью после того, как поймете это! Я думал просто записать шаги решения вопросов интервью, но не ожидал, что сразу столько напишу. Друзья, которые терпеливо читали здесь, все очень хорошие. Надеюсь, вы пойдете дальше и дальше по дороге технологий!