Говоря о цикле событий

JavaScript

предисловие

Author:@小yaoyao любит есть конфеты конфеты

В предыдущей статье@TDGardenСказал: "Сейчас время весеннего цветения и все восстанавливается. Все так заняты влюблённостью, что у них нет времени писать блоги".
Потом я прислал картинку мне в группу:

Сказал, что эта позиция мне подходит.
Итак, я понял. Мне пора вести блог. В конце концов, мы единственные, у кого есть время вести блог на фронтенде.

Что ж, не будем нести чушь, а перейдем к делу и поговорим о Event Loop. Эта статья является подведением итогов и подведением итогов изучения Event Loop за последние несколько дней.Она ссылается на статьи многих больших парней.Если есть какие-то ошибки,поправьте меня.

из одной нити

Как мы все знаем, js — это однопоточный язык. Почему однопоточный? Я цитирую плохую улицу: допустим, у js есть два потока одновременно, один поток хочет добавить контент в узел dom, а другой поток хочет удалить этот узел, какой из них должен превалировать? Конечно, решение многопоточности и многопоточности заключается в добавлении блокировок, но в этом случае будут привнесены такие проблемы, как блокировки и синхронизация состояний.

js — это язык сценариев для браузера. Его основная цель — взаимодействие с пользователями и работа с моделью DOM. Многопоточность вызовет сложные проблемы с синхронизацией.

Ну тогда однопоточная. Однако один поток приносит проблему одного потока. Существует только один поток, и задачи должны быть поставлены в очередь для выполнения. Если время выполнения предыдущей задачи очень велико (ajax запрашивает фоновые данные), последующие задачи должны ждать .

Появился Event Loop, чтобы взять на себя вину за один поток.

Event Loop

Прежде чем смотреть вниз, вы должны знать основные понятия стека, очереди, синхронной задачи, асинхронной задачи и стека выполнения.

По стеку выполнения есть очень подробная статья-рекомендация:Углубленный стек контекста выполнения JavaScript

Пожалуйста, посмотрите на изображение ниже:

  1. Когда js выполняет код, код сначала попадает в стек выполнения, и код может содержать некоторые синхронные задачи и асинхронные задачи.

  2. Задача синхронизации выполняется немедленно, и после выполнения стек извлекается.

  3. Асинхронные задачи также распространеныajaxпросить,setTimeoutПодождите, когда код вызывает эти API, WebAPI обрабатывают эти проблемы, и стек выполнения продолжает выполняться.

  4. Когда асинхронная задача имеет текущий результат (когдаajaxКогда результат запроса возвращается), WebAPI помещает соответствующую функцию обратного вызова в очередь задач.

  5. Когда стек выполнения пуст, прочитайте первую функцию в очереди задач и поместите ее в стек выполнения.

Постоянно повторяется шаг 5. Когда стек выполнения пуст, система переходит к очереди задач и помещает первую функцию в стек для продолжения выполнения. Этот процесс повторяется непрерывно, что является циклом событий (Event Loop).

Давайте посмотрим на простую демонстрацию.

console.log(1);

setTimeout(() => {
    console.log(2);
}, 2000);

console.log(3);
  • console.log(1)Задача синхронизации, выход 1
  • setTimeoutАсинхронные задачи передаются в webapis для обработки.Через 2 с,console.log(2)войти в очередь задач
  • console.log(3)Задача синхронизации, выход 3
  • Стек выполнения пуст, система считывает события в очереди задач
  • воплощать в жизньconsole,log(2), выход 2

Макрозадачи и микрозадачи

Конечно, это еще не конец. Я считаю, что вы, должно быть, виделиprocess.nextTick,promiseЧто ж, в этот раз порядок выполнения будет немного сложным, посмотрите вниз.

Микрозадачи, макрозадачи и цикл событийЯ использовал очень распространенный пример, чтобы рассказать о разнице между макрозадачами и микрозадачами, поэтому я не буду здесь вдаваться в подробности. Неважно, если вы не хотите знать, потому что общих макрозадач и микрозадач всего несколько, просто запомните их.

  • Общие задачи макроса:script(整体代码),setTimeout,setInterval,I/O,setImmedidate
  • Общие микрозадачи:process.nextTick,MutationObserver,Promise.then catch finally

process.nextTickа такжеsetImmidateОн поддерживает только среду Node.

а также,process.nextTickСуществует операция вставки в очередь, то есть, когда он входит в очередь микрозадач, онprocess.nextTickвпереди другие микрозадачи.

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

ответь на два вопроса

Я так много говорил раньше, давайте попробуем воду с двумя вопросами ниже.

new Promise(resolve => {
    resolve(1);
    Promise.resolve().then(() => console.log(2));
    console.log(4);
}).then(t => console.log(t));
console.log(3);

hahahhhhh Я переехал вопрос Учителя Руана.

  • первыйnew Promiseвоплощать в жизнь,resolve(1)Указывает, что состояние созданного объекта обещания становится разрешенным.
  • Promise.resolve()Это эквивалентно созданию объекта обещания, после чего анонимная функция обратного вызова входит в очередь микрозадач.[() => console.log(2)]
  • выход 4
  • new PromiseАнонимный обратный вызов в функции then входит в очередь микрозадач, а очередь микрозадач в это время[() => console.log(2), t => console.log(t)]
  • выход 3

Итак, окончательная выходная последовательность 4 3 2 1.

эммммммм, если вы не понимаете, то я думаю, вы можете сначала просмотреть егоpromise.

async function async1() {
  console.log('async1 start');
  await async2();
  console.log('async1 end');
}
async function async2() {
  console.log('async2');
}
console.log('script start');
setTimeout(function() {
  console.log('setTimeout');
}, 0);
async1();
new Promise(function(resolve) {
  console.log('promise1');
  resolve();
}).then(function() {
  console.log('promise2');
});
process.nextTick(() => {
  console.log('nextTick');
})
console.log('script end');

Это дерьмовый вопрос интервью. . Я не верю, что ты этого не видел. Не мудрствуя лукаво, давайте разберем эммммм Предлагаю сначала сделать это самому, а потом уже смотреть вниз.

Видетьasync/awaitНе нервничайте, это просто синтаксический сахар.asyncУказывает, что в функции есть асинхронная операция,awaitКак выполнить предыдущий код как выполнить,awaitВыражение справа выполняется как обычно, а следующий код заблокирован, ожидаяawaitвозвращение. вернуть истинуpromiseобъект, выполните следующий код; вернитеpromiseобъект и т.д.promiseобъектresolvedвыполнить снова.

Таким образом, можно понять, что код позади размещенpromise.thenв.

  • выходscript start
  • WebAPI помещаются после 0 с (о, самое короткое, кажется, 4 мс)setTimeoutАнонимная функция обратного вызова внутри выбрасывается в очередь задач макроса, сокращенно['setTimeout'](Помните, что в очередь задач выбрасывается callback-функция, функция!)
  • выходasync1 start
  • выходasync2
  • выводитьasync1 endМикрокод кидается в очередь задач, затем очередь задач для микро['async1 end']
  • выходpromise1
  • promiseСостояние объекта становитсяresolved
  • promise.thenАнонимная функция входит в очередь микрозадач, и очередь микрозадач в это время['async1 end', 'promise2']
  • nextTickСократите очередь до головы очереди микрозадач,['nextTick', 'async1 end', 'promise2']
  • выходscript end
  • Стек выполнения пуст
  • выходnextTick
  • выходasync1 end
  • выходpromise2
  • Очередь микрозадач пуста
  • выходsetTimeout

Эпилог

Если вы все еще не поняли после прочтения этой статьи, то я предлагаю вам прочитать еще несколько статей.Если одного печенья мало, десяти почти достаточно.

относится кpromise,async/await,NodeВ этой статье подробно не обсуждается разница между циклом событий и средой браузера, но эти знания помогут вам лучше понять цикл событий.

прочитай этоpromiseВы можете проверить воду, ответив на следующие вопросы:Eventloop — это не страшно, страшно встретить Promise.

Справочная статья