Javascript event loop

尽人皆知, javascript是一个单线程言语。单线程也就意味着只要一个stack(挪用栈),一次只能做一件事。那末又是怎样完成异步操纵?先来相识几个症结的术语。

Call Stack 挪用栈

《Javascript event loop》
如图所示,在运转历程当中,一切相干的变量是存于heap中,而call stack中是正在实行的代码。经由历程F12 developer tool 在debug情势也能够看到此时的call stack状况。下图是最简朴的一种状况,函数依据挪用递次顺次进入call stack,实行后再顺次弹出(stack后进先出)。

《Javascript event loop》

Task Queue

那末JavaScript是怎样完成异步的呢?主要的task queue(使命行列)来了。
一般而言,我们所明白的异步操纵,都是放入task queue举行守候。以下代码所示,console.log(‘start’)进入call stack。而setTimeout是进入task queue举行守候。这里设置的时刻为0,则是马上放入task queue,⚠️ 是放入task queue而不是马上实行。
只要在call stack为空的时刻,event loop会讲task queue中的使命调入call stack再实行。

console.log('start');

setTimeout(()=>{
    console.log('hey')
}
, 0)

console.log('end');

输出效果:

start
end
hey

《Javascript event loop》

Macrotask

一般而言,macrotask queue就是我们常说的task queue(也有人称为message queue)。Macrotask包含了setTimeout, Dom 操纵(比方onLoad), click/mouse事宜绑定,fetch response这类操纵。实际上这些都是浏览器供应的API,所以在实行时是有它们零丁的线程去举行操纵。举个例子,setTimeout()设置了2s的耽误,是浏览器设置了timer来计时,是别的的线程在守候2秒,js主线程不受影响,2s后回调函数再进入task queue。

(function() {

  console.log('this is the start');

  setTimeout(function cb() {
    console.log('this is a msg from call back');
  });

  console.log('this is just a message');

  setTimeout(function cb1() {
    console.log('this is a msg from call back1');
  }, 0);

  console.log('this is the end');

})();

// "this is the start"
// "this is just a message"
// "this is the end"
// undefined (注重此时是函数返回,由于没有设置返回值故输出undefined) 
// "this is a msg from call back"
// "this is a msg from call back1"

Microtask

ES6供应了Promise来举行异步操纵。为了区别开task称为microtask。同上也有一个queue (job queue)来处置惩罚microtask。job queue具有更高的优先级。每一个task完毕后,都邑举行perform a microtask checkpoint.也就是搜检job queue是不是有microtask在守候实行,依据先进先出,顺次实行。

console.log('script start');

setTimeout(function() {
  console.log('setTimeout');
}, 0);

Promise.resolve().then(function() {
  console.log('promise1');
}).then(function() {
  console.log('promise2');
});


// script start
// promise1
// promise2
// setTimeout

Event loop

简朴来讲,event loop会搜检queue是不是有须要处置惩罚的task,假如call stack为空时,则会根据先进先出的递次来处置惩罚queue中的task。而task分为microtask【Promise】和macrotask【setTimeout/DOM events/fetch】。优先处置惩罚microtask。一次event loop只会处置惩罚一次macrotask,并且是当microtask queue都处置惩罚完毕后才会去处置惩罚macrotasks。

while (queue.waitForMessage()) {
  queue.processNextMessage();
}

强烈推荐人人去看 https://jakearchibald.com/201… 作者用动画的情势异常抽象清楚地形貌了历程。

参考文章

  1. The JavaScript Event Loop
  2. JavaScript Event Loop Explained
  3. EventLoop | MDN
  4. Tasks, microtasks, queues and schedules
    原文作者:lsxj
    原文地址: https://segmentfault.com/a/1190000018783724
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞