非同步概念
對於 js 不知道非同步是什麼,為什麼需要有非同步的同學來說,可以先看看我的這篇文章 如錯誤之處,請求指點,謝謝閱讀。
非同步進一步理解
對於已經瞭解了非同步的基本概念的同學,我們可以來看一下,下面的這個例子,有助於我們更好的理解非同步(注意chrom: 版本:72.0.3626.121 版本不同結果有點差異)
複製程式碼
// 今日頭條面試題
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')
})
async1()
new Promise(function (resolve) {
console.log('promise1')
resolve()
}).then(function () {
console.log('promise2')
})
console.log('script end')
// result:
// script start
// async1 start
// async2
// promise1
// script end
// async1 end
// promise2
// settimeout
複製程式碼
執行過程的分析:
- 遇到 console.log('script start'), 放在主執行緒中立即執行,所以第一步先輸出 script start
- 遇到 setTimeout,因為 setTimeout 是非同步的,所以將回撥函式放入非同步佇列中去等待,等待主執行緒中的任務執行完之後,再通過事件輪詢的方式去呼叫
- 遇到 async1 函式的呼叫,此時走到 async1 函式裡面輸出 async1 start
- 遇到 await 關鍵字,進入到 async2 函式中輸出 async2,將 await 後面的程式碼放入微任務中,執行後面的操作
- 遇到 Promise 直接輸出promise1,將回撥函式放入微任務中,執行後面的操作
- 遇到 console.log('script end'), 放在主執行緒中立即執行,所以第一步先輸出 script end,到這個時候主執行緒中的程式碼就執行完了
- 主執行緒中的程式碼執行完之後,立即執行所有的微任務。分別輸出 async1 end,promise2
- 最後通過事件輪詢的方式將非同步佇列中程式碼,拿到主執行緒中來執行 (輸出 settimeout)
- 重複步驟8
注意
- await 關鍵字必須在用 async 關鍵字修飾的函式中才能使用。
- async 語法其實也就是 Promise 語法。
上面例子中的這部分程式碼可以轉化為:
轉化前:
async function async1() {
console.log('async1 start')
await async2()
console.log('async1 end')
}
複製程式碼
轉化後:
async function async1() {
console.log('async1 start')
new Promise((resolve, reject) => {
this.async2()
resolve()
})
.then(body => {
console.log('async1 end')
})
}
複製程式碼
為了鞏固大家可以練下下面兩個題目:
async function async1() {
console.log('async1 start');
await async2();
setTimeout(function() {
console.log('setTimeout1')
},0)
}
async function async2() {
setTimeout(function() {
console.log('setTimeout2')
},0)
}
console.log('script start');
setTimeout(function() {
console.log('setTimeout3');
}, 0)
async1();
new Promise(function(resolve) {
console.log('promise1');
resolve();
}).then(function() {
console.log('promise2');
});
console.log('script end');
複製程式碼
async function async1() {
console.log('async1 start')
await async2()
console.log('async1 end')
}
async function async2() {
console.log('async2')
new Promise((resolve, reject) => {
console.log('promise3')
resolve()
})
.then(body => {
console.log('promise4')
})
}
console.log('script start')
setTimeout(function () {
console.log('settimeout')
})
async1()
new Promise(function (resolve) {
console.log('promise1')
resolve()
}).then(function () {
console.log('promise2')
})
console.log('script end')
複製程式碼
答案:
script start
async1 start
promise1
script end
promise2
setTimeout3
setTimeout2
setTimeout1
複製程式碼
script start
async1 start
async2
promise3
promise1
script end
promise4
async1 end
promise2
settimeout
複製程式碼
謝謝大家的閱讀,不對之處,請指教。