之前对于异步也就停留在 async/await 的使用及简单的一些理解上,最近工作碰到一些问题,解决之后来做个记录。
在此之前首先要知道什么是异步,异步都有哪些,假如 await console.log('异步?') 显然此刻的await是形同虚设和console.log('异步?')效果是一样的。也就是说async/await只有用在异步操作上才生效,否则形同虚设。
假如现在有个场景,我们需要同时调用三个api(api请求当然就是异步操作了),我们想要在api请求成功之前给页面加一个loading,但是我们要求第一个api返回之后取消loading,再进行下面两个api的请求,这时候我们可以用Promise.race或者Promise.all也可以用async/await ,但是需要注意的是他们的区别,也就是我们要怎么用。
首先看看
Promise.race和Promise.all的区别:
Promise.all可以将多个Promise实例包装成一个新的Promise实例。同时,成功和失败的返回值是不同的,成功的时候返回的是一个结果数组,而失败的时候则返回最先被reject失败状态的值,且其中一个失败就代表失败。
let p1 = new Promise((resolve, reject) => {
resolve('成功了')
})
let p2 = new Promise((resolve, reject) => {
resolve('success')
})
let p3 = Promse.reject('失败')
Promise.all([p1, p2]).then((result) => {
console.log(result) //['成功了', 'success']
}).catch((error) => {
console.log(error)
})
Promise.all([p1,p3,p2]).then((result) => {
console.log(result)
}).catch((error) => {
console.log(error) // 失败了,打出 '失败'
})
Promse.racerace顾名思义就是赛跑的意思,意思就是说,Promise.race([p1, p2])里面哪个结果获得的快,就返回那个结果,不管结果本身是成功状态还是失败状态。
let p1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('success')
},1000)
})
let p2 = new Promise((resolve, reject) => {
setTimeout(() => {
reject('failed')
}, 500)
})
Promise.race([p1, p2]).then((result) => {
console.log(result)
}).catch((error) => {
console.log(error) // 打印的是 'failed',因为reject只需要0.5秒
})
对应到我们的需求我们可以
const p1 = '第一个api请求' // 这里用文字代表api请求了
Promise.race([p1]).then((result) => { //结合上面的解释,这里我们用Promise.all是一样的效果
// 这里请求成功,返回值,但是我们不需要在这里有什么操作
}).catch((error) => {
// 这里请求失败,返回值,我们做了统一的错误处理,所以也不需要做什么操作
})
this.loading = false // 我们在此处把loading关掉即可,总不能一直让也面处于loading状态
// 然后我们在进行下面的两个api请求即可
const p2 = '第二个api请求'
const p3 = '第三个api请求'
说完了Promise.race和Promise.all,我们来看看 async/await是如何解决问题的。
假如我们
async doSomething () { // await肯定要用在 async函数里面
await this.getFirstApi() //此处getFirstApi代表第一个api请求
this.loading = false
this.getSecondApi() //此处模拟第二个api请求
this.getThirdApi() //此处模拟第三个api请求
}
像上面这种写法肯定是不行的,因为假设第一个请求'挂掉'了,那么我们下面两个api请求将被'卡死'在这个地方,永远不会继续下去,所以我们需要借用try/catch来解决一下
async doSomething () { // await肯定要用在 async函数里面
try {
await this.getFirstApi() //此处getFirstApi代表第一个api请求
} catch {
//这里请求失败,做了失败处理
}
this.loading = false
this.getSecondApi() //此处模拟第二个api请求
this.getThirdApi() //此处模拟第三个api请求
}
这样的话我们就可以保证首先请求第一个api,且第一个api处理过后取消页面loading状态,又不会卡住剩下的两个api的请求了。