從例子中瞭解js的執行機制和異步

setTimeout(function() {
    console.log('setTimeout');
})
new Promise(function(resolve) {
    console.log('promise');
}).then(function() {
    console.log('then');
})
console.log('console');
複製代碼
  • 整段代碼作爲宏任務,進入主線程
  • 遇到setTimeout,將其回調函數註冊後分發到宏任務事件隊列中(做爲下一次循環宏任務調用)
  • 接下來遇到了Promisenew Promise當即執行,打印'promise',then函數分發到微任務事件隊列(本次宏任務的微任務)
  • 遇到console.log(),當即執行
  • 總體代碼做爲第一次循環的宏任務執行結束,查看還有微任務then,執行
  • 開始第二次循環,執行setTimeout,打印'promise'
  • 結果:promise, console, then, setTimeout
console.log('Hello World!');
const p1 = new Promise((resolve) => {
  console.log(3);
  resolve(4);
});
const p2 = new Promise((resolve) => {
  console.log(1);
  setTimeout(() => {
    console.log(6)
  }, 0);
  resolve(2);
});
p1.then((res) => {
  console.log(res)
});
p2.then((res) => {
  console.log(res)
});
console.log(5);
複製代碼
  • 總體代碼做爲宏任務進入主線程,先執行打印'hello world'
  • 而後p1中打印'3',resolve(4)then函數中分發到微任務事件隊列
  • 而後進入p2中打印'1',遇到setTimeout,將其回調函數註冊分發到宏任務事件隊列
  • resolve(2)then函數中分發到微任務事件隊列;向下執行,再打印'5'
  • 第一次循環的宏任務執行完,查看微任務事件隊列,先打印'4',再打印'2'
  • 第二次循環,執行宏任務中的setTimeout,打印'6'
  • 結果:hello world,3,1,5,4,2,6
console.log('1');
setTimeout(function first () {
    console.log('2');
    setTimeout(function third () {
      new Promise(function(resolve) {
        console.log('3');
        resolve();
    }).then(function() {
        console.log('4')
      })
    })
})
new Promise(function(resolve) {
    console.log('5');
    resolve();
}).then(function() {
    console.log('6')
})
setTimeout(function second () {
    console.log('7');
    new Promise(function(resolve) {
        console.log('8');
        resolve();
    }).then(function() {
        console.log('9')
    })
})
複製代碼
  • 總體代碼做爲第一次宏任務,進入主線程執行,先打印'1',再將setTimeout的回調函數first註冊分發到宏任務事件隊列
  • 向下執行,進入Promise中打印'5',then函數分發到微任務事件隊列
  • 再遇到一個setTimeout,將其回調函數second註冊分發到宏任務事件隊列中
  • 第一次循環的宏任務完成,執行微任務的then函數,打印'6'
  • 開始第二次循環,執行宏任務隊列中的first函數打印'2';而後又遇到了setTimeout函數,將third函數註冊分發到宏任務事件隊列中(下次循環纔會調用)
  • 接着,執行本次宏任務隊列中的second函數打印'7',進入promise打印'8',then函數註冊分發到微任務事件隊列
  • 第二次循環的宏任務完成,執行微任務的then函數,打印'9'
  • 開始第三次循環,執行宏任務隊列中third函數,先打印'3',再執行then中打印'4'
  • 結果:1,5,6,2,7,8,9,3,4

總結

  • 全部的同步任務都在主線程上執行,造成一個執行棧javascript

  • 主線程以外,還存在一個任務隊列,只要異步任務有了運行結果,就在任務隊列中放置一個事件java

  • 一旦執行棧中全部同步任務執行完畢,系統就會讀取任務隊列中的事件,異步任務結束等待狀態,進入執行棧,開始執行node

  • 重複上一步(事件輪循——重複讀取主線程和任務隊列中的事件)promise

  • 在js中的任務作更精確的定義:異步

    • macro-task(宏任務): 總體代碼js,setTimeout,setInterval
    • micro-task(微任務): Promise.then,process.nextTick(node.js)
  • 在本次循環執行中,先執行宏任務,再執行微任務,都完成後,開始第二輪循環,執行宏任務,執行微任務,直到沒有宏任務,完成執行函數

  • 圖片來源post

相關文章
相關標籤/搜索