EventLoop

毋庸置疑,你們都很瞭解js是一門單線程語言,這也就說明JS沒法進行多線程,可是JS中異步的功能徹底能夠模擬多線程,並且效果還槓槓滴。固然,若是想徹底理解異步,首先要了解JS的運行核心——事件環(Event Loop),下面分兩部分理解事件環:node

一:瀏覽器中的事件環(Event Loop)

  1. 爲了能更好的理解JS在瀏覽器中的任務隊列和事件循環,請看下圖:

  • eventLoop 是由JS的宿主環境(瀏覽器)來實現的;
  • 事件循環能夠簡單的描述爲如下四個步驟:
1. 函數入棧,當Stack中執行到異步任務的時候,就將他丟給WebAPIs,接着執行同步任務,直到Stack爲空;
2. 此期間WebAPIs完成這個事件,把回調函數放入隊列中等待執行(微任務放到微任務隊列,宏任務放到宏任務隊列)
3. 執行棧爲空時,Event Loop把微任務隊列執行清空;
4. 微任務隊列清空後,進入宏任務隊列,取隊列的第一項任務放入Stack(棧)中執行,回到第1步。

複製代碼
  1. 認識瀏覽器中的任務源(task):
  • 微任務:then 、messageChannel 、mutationObersve
  • 宏任務:setTimeout、setInterval、setTmmediate(只兼容ie)
  1. 下面實現一個小例子:
console.log(1);
console.log(2);
setTimeout(function () {
  console.log('setTimeout1');
  Promise.resolve().then(function () {
    console.log('promise');
  });
});
setTimeout(function () {
  console.log('setTimeout2');
});

複製代碼

打印結果:promise

1
2
setTimeout1瀏覽器

promisebash

setTimeout2多線程

二:Node 環境中的事件環(Event Loop)

  1. 爲了能更好的理解JS在Node環境中的任務隊列和事件循環,請看下圖:

  • 圖雖然有些亂,可是咱們只需關心timers計時器階段和poll輪詢階段,check檢查階段便可,clons關閉階段以及微任務隊列便可。異步

  • Node 環境中微任務是插縫執行,(若是執行宏任務的時候發現了微任務, 不會像瀏覽器同樣執行了,而是將爲微任務放到微任務隊列中,等待整個宏 任務隊列執行完畢或者達到執行上線後,下一個階段開始的時候先執行 完微任務隊列中的任務)。函數

  1. 認識Node中的任務源(task):
  • 微任務: then 、nextTick 、 messageChannel 、mutationObersve
  • 宏任務:setTimeout 、setInterval 、setImmediate 、io文件操做
  1. 例一:timeout、immediate 兩個誰先執行不必定 取決於node的執行時間。
setTimeout(function () {
    console.log('setTimeout1');
})
setImmediate(function () {
    console.log('setImmediate2');
});
複製代碼
打印結果有兩種:
  • 1) setTimeout1 setImmediate2
  • 2) setImmediate2 setTimeout1
  1. 例二: 若是i/o文件操做之後就會先執行setImmediate,由於setImmediate在i/o文件操做後面的那個階段執行,執行完setImmediate會在下一個階段的時候再執行setTimeout (timers 計時器執行階段)
let fs = require('fs');
fs.readFile('1.log', function () {
  console.log('fs');
  setTimeout(function () {
    console.log('timeout');
  });
  setImmediate(function () {
    console.log('mmiediate');
  });
});

複製代碼
打印順序結果
  • fs 、 miediate、 timeout
  1. 例三: 微任務中nextTIck 會比then先執行。
Promise.resolve().then(function () {
  console.log('then2'):
});
process.nextTick(function () {
  console.log('nextTick1');
});


複製代碼
打印順序結果
  • nextTick1 then2
  1. 例四: 微任務會優先與i\o文件操做執行。
let fs = require('fs');
fs.readFile('./1/log',function(){
    console.log('fs')
})
process.nextTick(function(){
    console.log('text2');
})

複製代碼
打印執行結果
  • text2 fs

好了,今天就到這,若有錯誤,請下方留言。做爲碼農一枚,最大的願望和最偉大的理想是,大寶每天見,bug死生不復相見,相忘於江湖,恩怨一筆消失!!!oop

相關文章
相關標籤/搜索