1. 程式人生 > 其它 >JavaScript非同步程式設計(五)之async和巨集任務微任務

JavaScript非同步程式設計(五)之async和巨集任務微任務

技術標籤:javascript前端

Promise 雖然主要是用來處理非同步任務的,但我們深入理解 Promise 並不是純為了來處理非同步任務,因為在 ES7 裡的 async 和 wait 能更簡單的處理非同步任務:

// 一個非同步任務,在time毫秒後返回一個狀態為reject的Promise物件
function ajax(time) {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve(`完成了-${time}`)
        }
, time) }) } // 主函式 async function main() { const ajax1 = await ajax(600) console.log(ajax1) const ajax2 = await ajax(500) console.log(ajax2) const ajax3 = await ajax(700) console.log(ajax3) } main()

如上程式碼,在主函式前新增關鍵字 async ,主函式裡面的每個非同步任務前加上關鍵字 await ,並分別用一個變數接收返回值,非同步任務處理便完成了。

上邊程式碼按順序執行:
在這裡插入圖片描述
可見,上面的3個非同步任務雖然耗時各不相同,但都按照執行的先後順序完成,並不會受耗時長短的影響。

稍加完善,正式專案中程式碼可能如下:

async function main() {
	try {
		const users = await ajax('/api/users.json')
		console.log(users)

		const posts = await ajax('/api/posts.json')
		console.log(posts)

		const urls = await ajax('/api/urls.json')
		console.log
(urls) } catch (e) { console.log(e) } }

async 和 wait 就是這麼樸實無華,需要注意的是 await 不能單獨使用,必須在 async 修飾的主函式裡使用,不過 await 單獨使用的提案已經提出,也許不久的將來 await 就可以單獨使用了,那時將更加的方便。

巨集任務和微任務

先看一段程式碼:

console.log('start')

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

new Promise((resolve, reject) => {
    console.log('promise')
    resolve('then')
}).then(res => {
    console.log(res)
})

console.log('end')

上面程式碼的執行順序,估計很多人都理不對,正常的執行順序如下:
在這裡插入圖片描述
這裡涉及巨集任務和微任務的概念。

new Promise() 本身和同步任務執行模式沒區別,會直接執行,不會去訊息佇列裡排隊,所以在第一輪執行中,所有同步任務會按續執行,即按續列印:“start”、“promise”、“end”。

執行到 setTimeout() 的時候,會產生一個巨集任務,這個巨集任務會進入到訊息佇列中排隊,等待同步任務執行完之後才會執行。

在 new Promise() 執行的時候,它後面的 then 產生一個微任務,這個微任務也會進入訊息佇列中排隊,等待同步任務執行完之後才會執行。

同步任務執行完之後,此時訊息佇列中有一個巨集任務和一個微任務,微任務的執行優先度比巨集任務高,所以先執行微任務,再執行巨集任務,所以隨後先後列印:“then”、“setTimeout”。

如果你覺得理解了巨集任務微任務,那麼再看看下面這個程式碼:

new Promise((resolve, reject) => {
    console.log(1)
    resolve()
}).then(() => {
    console.log(2)
}).then(() => {
    console.log(3)
})

new Promise((resolve, reject) => {
    console.log(111)
    resolve()
}).then(() => {
    console.log(222)
}).then(() => {
    console.log(333)
})

執行試試吧,看看是否與預想的一樣?

文章內容輸出來源:拉勾大前端高薪訓練營,以上文章中的內容根據老師講課的語音和程式碼,結合自己的理解編輯完成。