很久没写博客了,今天终于把拖了很久的一篇写完了。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,能够很好提高代码的可阅读和可维护性,你们若是还有更好的用法和建议,欢迎在评论区补充。