Цикл событий JS

Node.js внешний интерфейс Promise
Писать статьи о SETTIMEOUT на прошлой неделе, на самом деле, это также задействовало операционный механизм JS. Итак, на этой неделе поговорим о механизме запуска JavaScript.

Тогда сначала задайте вопрос 😁.

Почему JavaScript однопоточный?

Позвольте мне ответить:

Однопоточность означает, что одновременно может выполняться только одно действие. Разве это не неэффективно? Нет, на самом деле однопоточная особенность javascript связана с его назначением. В качестве языка сценариев браузера JavaScript в основном используется для взаимодействия с пользователем и управления DOM. Если это не один поток, когда один поток добавляет содержимое в узел DOM, другой поток удаляет содержимое этого узла DOM, это нормально, разве это не беспорядок. Таким образом, javascript может быть только однопоточным.

Хотя javascript является однопоточным, в javascript есть концепция синхронизации и асинхронности, которая решает проблему блокировки js.

Синхронные и асинхронные:

1. Синхронизация:

Если функция возвращает значение, вызывающая сторона может получить ожидаемый результат (то есть получить ожидаемое возвращаемое значение или увидеть ожидаемый эффект), то функция является синхронной.

Объясните кодом:

console.log('Hello');

Если вы видите ожидаемый эффект при возврате функции: Hello выводится на консоль

2. Асинхронный:

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

Объяснение кода:

fs.readFile('test.txt', 'utf8', function(err, data) {
    console.log(data);
});

В приведенном выше коде мы хотим прочитать содержимое файла foo.txt с помощью функции fs.readFile и распечатать его. Но когда функция fs.readFile вернется, ожидаемого нами результата не произойдет, а будет ждать, пока файл будет полностью прочитан. Это может занять много времени, если файл большой.

Небольшое резюме:

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

  2. Вызов асинхронного метода больше похож на передачу сообщения: после запуска вызов метода немедленно возвращается, и вызывающая сторона может продолжать последующие операции. Однако асинхронные методы обычно выполняются "реально" в другом потоке. Весь процесс не будет мешать работе звонящего.

javascript может выполнять синхронные задачи и асинхронные задачи. Поставив операции чтения файлов и ajax-запросов в очередь задач, я все равно могу пошагово продолжить выполнение следующих задач. Итак, javascript все еще может быть очень 6. Итак, асинхронная задача — это только задача на выполнение асинхронной операции, и что в ней будет происходить?

Очередь задач:

Как упоминалось выше, в javascript есть два типа задач: синхронные задачи и асинхронные задачи.

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

Асинхронные задачи относятся к тому, что они не входят в основной поток и входят в задачу «очереди задач», только «Запрос задачи» уведомляет основной поток, и некоторые асинхронные задачи могут быть выполнены, задача войдет в основной поток.

Давайте посмотрим на маленький каштан:

console.log("a");
setTimeout(function () {
    console.log("b");
},0);
console.log("c");

//a
//c
//b

Код в js выполняется сверху вниз.При выполнении первой строки кода консоль выводит a.При выполнении второй строки кода встречается функция setTimeout.Поскольку функция setTimeout является асинхронной функцией, браузер запомнит это событие, добавит его в расписание, а затем поместит функцию обратного вызова этого события в очередь задач. В это время программа основного потока продолжает выполняться до пятой строки: console.log("c"), выполнить это, и консоль выводит c. В это время основной поток пуст, и он отправится в очередь задач, чтобы узнать, есть ли какие-то задачи, которые можно выполнить.

Чтобы лучше проиллюстрировать очередь задач и цикл событий, давайте посмотрим на схему. 😄

Эта картинка уже нарисовала поток событийного цикла js. обработать:

  1. Все задачи синхронизации выполняются в основном потоке, образуя стек выполнения.
  2. Когда стек выполнения в основном потоке пуст, проверяем, пуста ли очередь событий, если пуста, продолжаем проверку, если не пуста, выполняем 3;
  3. Извлеките голову очереди задач и поместите ее в стек выполнения;
  4. выполнять задания;
  5. Проверить стек выполнения, если стек выполнения пуст, вернуться к шагу 2, если нет, продолжить проверку;

Цикл событий:

Цикл событий на самом деле является циклом, который выталкивает и извлекает стек. В приведенном выше примере упоминается setTimeout, а как насчет setInterval, Promise и т.д. и т.п., там много асинхронных функций. Но эти асинхронные задачи делятся на макрозадачи и микрозадачи:

Макрозадачи включают в себя: скрипт setTimeout, setInterval, setImmediate, ввод-вывод, рендеринг пользовательского интерфейса.

Микрозадача включает в себя: process.nextTick, Promises, Object.observe, MutationObserver.

Каждый раз, когда петли события пожары:

  1. Выполнение задач в основном потоке выполнения — это выполнение первой задачи макрозадачи, такой как задача сценария.
  2. Выньте выполнение задачи в микрозадаче, пока она не будет очищена.
  3. Вынести выполнение задачи в макро-задачу.
  4. Выньте выполнение задачи в микрозадаче, пока она не будет очищена.
  5. Повторите 3 и 4.
По сути, then и catch промисов — это микрозадачи, а не их собственный внутренний код.

Уведомление:

  1. Реализация в браузере браузера и узла отличается.

  2. Очередь задач "первым пришел, первым вышел".

Затем подойдите к маленькому каштану, чтобы проверить, полностью ли вы его поняли:
console.log('global')

for (var i = 1;i <= 5;i ++) {
  setTimeout(function() {
    console.log(i)
  },i*1000)
  console.log(i)
}

new Promise(function (resolve) {
  console.log('promise1')
  resolve()
 }).then(function () {
  console.log('then1')
})

setTimeout(function () {
  console.log('timeout2')
  new Promise(function (resolve) {
    console.log('timeout2_promise')
    resolve()
  }).then(function () {
    console.log('timeout2_then')
  })
}, 1000)

Вывод консоли:

Этот блог может быть очень полезен для углубления понимания:Глубокое понимание цикла событий JavaScript (1) - цикл событий

Суммировать:

В основном это касается цикла событий js на стороне браузера. Эта статья может помочь лучше понять различные циклы обработки событий в средах узлов и браузеров:Различные циклы событий браузера и узла (Event Loop)