передовой
Жила-была гора, а в горе был храм, В храме был маленький монах, рассказывавший истории, о чем он говорил? Говоря о:
Жила-была гора, а в горе был храм, В храме был маленький монах, рассказывавший истории, о чем он говорил? Говоря о:
Жила-была гора, а в горе был храм, В храме был маленький монах, рассказывавший истории, о чем он говорил? Говоря о:
...
Пожалуйста, прочитайте короткий рассказ
Раньше был ресторан с владельцем и шеф-поваром, он начал свой бизнес, сначала у него не было средств на найм сотрудников, поэтому он стал владельцем и официантом.
Есть четыре типа клиентов, которые приходят в этот ресторан
- Супер VIP-клиент
- VIP-клиенты
- обычный клиент
- просроченные клиенты
Как VIP-клиент, вы должны иметь VIP-привилегии.
- Приоритетное обслуживание
- Тот же VIP, первый заказ обслужен первым
Поэтому порядок обслуживания в этом магазине связан с идентичностью и порядком заказа.
Супер VIP-клиент > VIP-клиенты > обычный клиент > просроченные клиенты
Однажды, после того как босс открылся, несколько человек зашли один за другим, чтобы заказать и поесть.
-
Первый, кто войдет, этообычныйклиентов, заказавшихвареное мясо
-
Второй пришел с деньгами.VIPзаказ покупателярак
-
Вошел третийПо умолчаниюклиентов, которые заказали много
-
Приходит четвертый -Супер VIP-клиент, нажалМаринованная рыба
Поскольку в этом ресторане всего один человек, босс развлек их и пошел жарить после того, как они заказали. Согласно указанному выше порядку, так будет жарить первымСупер VIP-клиентзаказ, а затемVIP-клиентызаказ, а затемобычный клиентЗаказали блюда, наконец-то приехалипросроченные клиентызаказ
давайте использоватьПоддельный кодПосмотрите, как реализовать эту логику
Мы определяем четыреfunction
- superVipOrder(имя, блюдо) используется для представленияСупер VIP-пользовательЗаказ а ля карт
- vipOrder(имя, блюдо) используется для представленияVIP-пользователиЗаказ а ля карт
- заказ (имя, блюдо) используется для представленияобычный пользовательЗаказ а ля карт
- groupOrder(имя, блюдо) используется для представленияпросроченные клиентыЗаказ а ля карт
В соответствии с правилами обслуживания, упомянутыми выше,
Супер VIP-клиент > VIP-клиенты > обычный клиент > просроченные клиенты
Фактический порядок обслуживания, который мы можем знать,
Так вот вопрос, теfunctionкто они такие?
На самом деле все очень просто, этиfunctionВсе соответствуют некоторым асинхронным функциям в JavaScript.
// 超级VIP客户
// 微任务,将回调加入到 执行队列,优先执行
function superVipOrder(name, dish, order) {
process.nextTick(() => {
console.log(red(`superVip顾客 ${name} 点了 ${dish} 已经上了`));
});
}
// VIP客户
// 微任务,将回调加入到 执行队列,优先执行,优先级比process.nextTick低
function vipOrder(name, dish, order) {
new Promise((resolve, reject) => {
resolve(true);
}).then(() => {
console.log(blue(`vip顾客 ${name} 点了 ${dish} 已经上了`));
});
}
// 普通客户下单
// 宏任务,将回调加入到 宏任务的执行队列中
function order(name, dish, order) {
setTimeout(() => {
console.log(yellow(`普通顾客 ${name} 点了 ${dish} 已经上了`));
}, 0);
}
// 赖账的客户下单
function groupOrder(name, dish, order) {
setImmediate(() => {
console.log(green(`赖账的顾客 ${name} 点了 ${dish} 已经上了`));
});
}
Мы можем поставитьprocess.nextTickдумаю, что этосупер вип пользователь, наивысший приоритет,
РоднойPromiseдумаю, что этоVIP-пользователь, приоритет выполнения высокий
setTimeoutдумаю, что этообычный пользователь, приоритет выполнения нормальный
setImmediateдумаю, что этопросроченный клиент, приоритет выполнения низкий
восстановить псевдокод
Мы восстановим псевдокод этих асинхронных функций, что сделает нас более интуитивными и добрыми.
В соответствии с правилами приоритета, упомянутыми в приведенной выше истории, мы знаем, что вывод будет таким:
Почему это результат? Поговорим о цикле событий в JavaScript.
Event Loop
1. Цикл событий JavaScript
мы знаемJavaScriptОн однопоточный, как и босс в вышеприведенной истории, он должен подойти к официанту, чтобы обслужить гостей на заказ, и отдать меню шеф-повару, а затем шеф-повар подаст его ему после жарки. Если шеф не приглашает повара и готовит блюда сам, то нет возможности принимать гостей во время готовки, и гости будут ждать заказа. Ожидание и ожидание обнажит проблему плохого отношения к обслуживанию. Следовательно, должен быть повар, который специализируется на приготовлении пищи.
Итак, в js задачи делятся на синхронные задачи и асинхронные задачи,
- Задача синхронизации -> официант идет встречать гостей, чтобы заказать еду
- Асинхронная задача -> готовка шеф-поваром, асинхронная функция обратного вызова эквивалентна подаче еды официантом
Цикл событий JS показан на рисунке,
- При выполнении задачи основного потока, если есть асинхронная задача, она войдет в Таблицу событий и зарегистрирует функцию обратного вызова.Когда указанное дело будет выполнено, функция обратного вызова будет помещена вcallback queueсередина
- После того, как основной поток завершит выполнение, он будет читатьcallback queueФункция обратного вызова в , входит в основной поток для выполнения
- Этот процесс повторяется непрерывно, что часто называют Event Loop (цикл событий).
2. Асинхронные задачи
Асинхронные задачи делятся на макрозадачи и микрозадачи, разница между которыми в основном заключается в разнице в порядке выполнения.
В js микрозадачи есть
-
Родной Promise -> на самом деле то, о чем мы упоминали выше.VIP-пользователи,
-
process.nextTick -> на самом деле то, что мы упоминали вышеСупер VIP-пользователь,
process.nextTickприоритет выполнения выше, чемPromiseиз
задача макроса
- общий код скрипта
- setTimeout -> на самом деле то, что мы упоминали вышеобычный пользователь,
- setImmediate -> на самом деле то, что мы упоминали вышегруппа пользователей,
setTimeoutприоритет выполнения выше, чемsetImmediateиз
Процесс выполнения макрозадач и микрозадач
В цикле событий JS сначала выполнит весь кодscript, после выполнения он определит, есть ли микрозадачи в очереди микрозадач, и если да, то выполнит их одну за другой и одновременно выполнит макрозадачи. такой процесс
тестовое задание
Посмотрим, понимает ли кусок кода этот процесс
<script>
setTimeout(() => {
console.log('a');
new Promise( res => {
res()
}).then( () => {
console.log('c');
})
process.nextTick(() => {
console.log('h');
})
}, 0)
console.log('b');
process.nextTick( () => {
console.log('d');
process.nextTick(() => {
console.log('e');
process.nextTick(() => {
console.log('f');
})
})
})
setImmediate( () => {
console.log('g');
})
</script>
Результат выполнения:b d e f a h c g
Давайте проанализируем поток выполнения этого кода
-
Выполнение первой задачи макроса на главной странице Весь абзац
scriptКод этикетки, встретите первыйsetTimeout, добавьте его функцию обратного вызова вмакросочередь задач, -
выход
console.log('b') -
При встрече с process.nextTick добавьте его функцию обратного вызова вмикроЗадача
-
При встрече с setImmediate добавьте его функцию обратного вызова вмакросочередь задач
| Задача макроса Очередь событий | Очередь событий микрозадач |
|---|---|
| setTimeout | process.nextTick |
| setImmediate |
- Когда выполняется первая задача макроса, она определяет, есть ли ещемикрозадача только однамикроЗадача, выполнить обратный вызов process.nextTick, вывод
console.log('d'), а затем столкнулся с process.nextTick, который был помещен вмикроочередь задач - продолжатьмикроФункция обратного вызова из очереди задач вынимается, продолжает выполняться и выводится
console.log('e'), а затем столкнулся с process.nextTick, который был помещен вмикроочередь задач - продолжатьмикроФункция обратного вызова из очереди задач вынимается, продолжает выполняться и выводится
console.log('f'), а затем столкнулся с process.nextTick, который был помещен вмикроочередь задач
| Задача макроса Очередь событий | Очередь событий микрозадач |
|---|---|
| setTimeout | |
| setImmediate |
- Когда очередь микрозадач пуста, запустите новую макрозадачу, выньте функцию первой очереди макрозадач,
setTimeout,воплощать в жизньconsole.log('a'), а потом столкнутьсяPromise,process.nextTickдобавить свой обратный вызов вмикроочередь задач. После казни
| Задача макроса Очередь событий | Очередь событий микрозадач |
|---|---|
| setImmediate | promise.then |
| - | process.nextTick |
- продолжать судитьмикроЕсть ли в очереди задач функция обратного вызова для выполнения, потому что
process.nextTickимеет приоритет выполнения больше, чемpromise, поэтому он будет выполняться первымprocess.nextTickобратный вызов, выводconsole.log('h');, если их несколькоprocess.nextTickобратный звонок, будетprocess.nextTickВсе обратные вызовы будут выполняться после выполнения другихмикроОбратный вызов для задачи. Когда все обратные вызовы nextTick будут выполнены, выполнитеpromiseобратный вызов, выводconsole.log('c');, пока очередь обратного вызова обещания не будет выполнена, он будет судить, есть ли ещемикроЗадача.
| Задача макроса Очередь событий | Очередь событий микрозадач |
|---|---|
| setImmediate |
-
микрозадачиПосле выполнения начать выполнять новую задачу макроса, выполнить
setImmediateобратный вызов, выводconsole.log('g');
3. setImmediate
почему здесьsetImmediateВынеси его отдельно, потому что он относится к разряду макро задач, но он немного другой.
Посмотрите на кусок кода
Согласно нашей логике анализа выше, мы будем думать, что вывод этого кода должен бытьa b c d.
Если мы используем Node 0.10.x для выполнения этого кода, результатом будет действительно выводa b c d
Однако после версий Node выше 4.x после выполненияsetImmediateДа, цикл while будет использоваться для удаления всех немедленных обратных вызовов и их обработки по очереди.
ps: в узле 11 и выше setImmediate обрабатывается в соответствии с порядком выполнения макрозадач и не будет вызываться в цикле.
Наконец, взгляните на фрагмент кода, чтобы убедиться, что вы действительно его освоили.
Если вы еще не освоили его, добро пожаловать в комментарии
<script>
console.log("start");
process.nextTick(() => {
console.log("a");
setImmediate(() => {
console.log("d");
});
new Promise(res => res()).then(() => {
console.log("e");
process.nextTick(() => {
console.log("f");
});
new Promise(r => {
r()
})
.then(() => {
console.log("g");
});
setTimeout(() => {
console.log("h");
});
});
});
setImmediate(() => {
console.log("b");
process.nextTick(() => {
console.log("c");
});
new Promise(res => res()).then(() => {
console.log("i");
});
});
console.log("end");
</script>
Результат:start end a e g f h b d c i
Кратко проанализируем код:
- Начинается первый раунд цикла событий, выполняя
scriptкод,выходstartend,Будуprocess.nextTickОбратный вызов добавляется в очередь микрозадач, аsetImmediateОбратный вызов добавляется в очередь задачи макроса - Выполнение очереди микрозадач
process.nextTickобратный звонок,выходa,БудуsetImmediateОбратный вызов добавлен вмакросВ очереди заданий встретитеpromise, добавьте обратный вызов вмикров очереди задач.
| задача макроса | микрозадачи |
|---|---|
| setImmediate | promise.then |
| setImmediate | - |
- Продолжайте выполнять обратный вызов в очереди микрозадачи, выньте
promise.thenи выполнить,выходe,Будуprocess.nextTickОбратный вызов помещается в микрозадачу и встречаетpromise, добавьте обратный вызов вмикров очереди задач. - Определить, есть ли еще функция обратного вызова в очереди обратного вызова текущего промиса, которая не была выполнена.Если это так, она продолжит выполнение и уберет обратный вызов только что введенного промиса.выход
g, когда очередь обратного вызова Promise выполняется, продолжайте судить, есть ли еще микрозадачи. - выиграть
process.nextTickобратный вызов и выполнение,выходf
| задача макроса | микрозадачи |
|---|---|
| setImmediate | - |
| setImmediate | - |
| setTimeout | - |
- После того, как текущая очередь микрозадач опустеет, начните выполнение задачи макроса, т.к.
setTimeoutприоритет больше, чемsetImmediate, так выньsetTimeoutобратный вызов и выполнение,выходh - Текущая очередь микрозадач все еще пуста, начните выполнение макрозадачи и выньте все
setImmediateфункцию обратного вызова и выполнить,выходb d,Будуprocess.nextа такжеpromiseОбратный вызов помещается в очередь микрозадачи. - выигратьмикрозадачиФункция обратного вызова в очереди и выполняется,выход
c i
Суммировать
Как часто задаваемый вопрос в интервью, Event Loop несложно понять.
Оригинальная ссылка:C code.live/Len too/list…
Добро пожаловать, чтобы следовать
Добро пожаловать в общедоступный номер»разработка кода», делясь последней технической информацией каждый день