很久沒寫博客了,今天終於把拖了很久的一篇寫完了。git
原文地址:必須知道的 Promise 進階點(二)github
前面還有:必須知道的 Promise 進階點(一)web
比起回調函數那看不懂的嵌套,Promise 要清爽很多,但當任務較多時, Promise 也有可能會有比較長的鏈和嵌套,這時候使用 async/await 就會讓代碼易讀不少。異步
async 函數能夠看做是 Promise 的語法糖:async
// resolve 狀態
async function foo() {
console.log('start')
return 'resolve'
}
foo().then(data => {
console.log('data:', data)
})
console.log('end')
// start
// end
// data: resolve
// reject狀態
async function foo() {
console.log('start')
throw new Error('reject')
}
foo().catch(data => {
console.log('data:', data.message)
})
console.log('end')
// start
// end
// data: reject
複製代碼
與下面直接使用 Promise 方式書寫的效果如出一轍:函數
// resolve 狀態
function foo() {
return new Promise((resolve, reject) => {
console.log('start')
resolve('resolve')
})
}
foo().then(data => {
console.log('data:', data)
})
console.log('end')
// start
// end
// data: resolve
// reject狀態
function foo() {
return new Promise((resolve, reject) => {
console.log('start')
reject('reject')
})
}
foo().catch(data => {
console.log('data:', data)
})
console.log('end')
// start
// end
// data: reject
複製代碼
await 與其字面意思同樣——等待,等待其後的函數執行完畢。ui
// resolve狀態
async function foo() {
console.log('start')
return 'resolve'
}
async function bar() {
const data = await foo()
console.log('data', data)
}
bar()
console.log('end')
// start
// end
// data resolve
// reject狀態
async function foo() {
console.log('start')
throw new Error('reject')
}
async function bar() {
try {
const data = await foo()
console.log('data', data)
} catch (err) {
console.log('data', err.message)
}
}
bar()
console.log('end')
// start
// end
// data reject
複製代碼
await 只能在 async 函數裏使用,不然會報錯spa
首先思考下面兩個場景:code
有一個異步請求,須要屢次而且按順序發送隊列
有一個異步請求,須要屢次發送,但不用按順序
同一個請求,屢次,按順序。這就是一個典型的串行處理
function mockServer(i) {
return new Promise((reslove, rejecy)=> {
setTimeout(() => {
reslove('有值了:' + i)
}, 1000 * i)
})
}
async function getData(time) {
var data = await mockServer(time)
return data
}
var arr = [1,2,3,4]
async function showData() {
console.time('showData')
for (const item of arr) {
const data = await getData(item)
console.log(data)
}
console.timeEnd('showData')
}
showData()
// 有值了: 1
// 有值了: 2
// 有值了: 3
// 有值了: 4
// howData: 13100.510009765625ms
複製代碼
咱們經過 for-of
循環調用了 4 次異步函數 getData
,因爲 getData
前面加了關鍵字 await
,因此會依次排隊處理,一共花了13秒多的時間。
同一個請求,屢次,不按順序。這就是一個典型的並行處理,每一個請求同時發送,而不用排隊等候,節約時間。
function mockServer(i) {
return new Promise((reslove, rejecy)=> {
setTimeout(() => {
reslove('有值了:', i)
}, 1000 * i)
})
}
async function getData(time) {
var data = await mockServer(time)
return data
}
var arr = [1,2,3,4]
async function showData() {
console.time('showData')
var allAsyncRequest = arr.map(item => getData(item))
for await (const asyncRequest of allAsyncRequest) {
const data = asyncRequest
console.log(data)
}
console.timeEnd('showData')
}
showData()
// 有值了: 1
// 有值了: 2
// 有值了: 3
// 有值了: 4
// showData: 4131.318115234375ms
複製代碼
咱們在 map 的回調裏調用了 4 次異步請求函數,將請求事件放到事件隊列裏面,讓 4 個請求能夠同時處理,而不影響後續任務的執行。
而後再經過 for await...of
來等待 4 個異步請求都執行完,一共花了 4 秒,大大節約了時間。
這裏的 for await...of
還能夠換一種寫法:
for (const asyncRequest of allAsyncRequest) {
const data = await asyncRequest
console.log(data)
}
複製代碼
也可使用 Promise.all()
:
Promise.all(allAsyncRequest).then((data) => {
console.log(data)
console.timeEnd('showData')
})
// ["有值了:1", "有值了:2", "有值了:3", "有值了:4"]
// showData: 4441.679931640625ms
複製代碼
注意:這裏不能使用
forEach
來進行循環處理,具體緣由能夠看 當async/await趕上forEach,這篇文章已經寫的很清楚了。
學會熟練使用 async/await,能夠很好提高代碼的可閱讀和可維護性,你們若是還有更好的用法和建議,歡迎在評論區補充。