JavaScript异步编程(四)之Promise并行执行和超时处理
作者:互联网
并行执行
或许,可能有遇到过这样的需求:
- 一个接口的参数是由其他三个接口的返回值组合而成,因此这个接口必须要保证在另外三个接口完成之后才能被调用;
- 在echarts的图表中,一个图表中可以有好几组数据,每组数据都由一个接口返回,根据echarts使用规则,必须得这几个接口都请求完成之后才渲染图,比如下面这个,有四组数据在同一个echarts表里:
以上两种情况,都是需要在某几个接口请求完毕之后再执行另一个接口。
这个涉及到并行执行的概念,Promise.all() 刚好可以解决这个问题。
上代码:
// 仿一个ajax请求,传入一个数作为时间参数,会在对应时间之后返回一个结果
function ajax(time) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(`完成了-${time}`)
}, time)
})
}
// 三个ajax执行完后,才回执行then里的代码
Promise.all([
ajax(1000),
ajax(1500),
ajax(2000)
]).then(res => {
console.log(res)
})
Promise.all() 不再做过多讲解,总结一句话就是:
Promise.all()里面的方法都执行完毕后,才会调用then回调函数里面的代码,回调函数返回的值是一个数组,分别存放Promise.all() 里方法的返回信息。
比如,上边代码,会在执行两秒后,返回结果如下:
错误处理
那么,如果Promise.all里的方法有一个出错了该如何处理呢?
这需要针对每一个方法单独做处理,处理后的结果会被Promise.all接收:
function ajax(time) {
return new Promise((resolve, reject) => {
setTimeout(() => {
// 如果参数为1500,抛出一个错误
if (time === 1500) {
reject(new Error('参数不能为1500'))
}
resolve(`完成了-${time}`)
}, time)
})
}
// 每个请求做catch错误处理
Promise.all([
ajax(1000).catch(err => console.log(err)),
ajax(1500).catch(err => console.log(err)),
ajax(2000).catch(err => console.log(err))
]).then(res => {
console.log(res)
})
执行结果如下:
在并发执行的使用中,有一种优雅的写法,就是把所有需要并行执行的接口都写在一个接口里,请求这个接口后,将返回的接口通过循环来并行执行,代码如下:
ajax('/api/urls.json')
.then(value => {
const urls = Object.values(value)
const tasks = urls.map(url => ajax(url))
return Promise.all(tasks)
})
.then(values => {
console.log(values)
})
超时处理
先来看另一个方法:Promise.race()
上代码,来看个现象:
function ajax(time) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(`完成了-${time}`)
}, time)
})
}
Promise.race([
ajax(1000),
ajax(1500),
ajax(2000)
]).then(res => {
console.log(res)
})
和 Promise.all() 方法高度一致,只是将 all 换成了 race。
race 为竞赛之意,意思是说,Promise.race() 里的方法,只要有一个执行完成了,就会调用then方法里的回调函数,回调函数接收的是最早执行完的那个方法的返回信息。
所以如上代码会在执行一秒会返回:
那么这个方法有什么作用呢?它常常用在接口的超时处理上。
有一个接口,如果5秒内没返回结果,就报错,不再请求,可参考如下示例:
// 要7秒才能执行完
function ajax1() {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve('7秒后我才完成')
}, 7000)
})
}
// 5秒后,抛出一个错误
function timeout() {
return new Promise((resolve, reject) => {
setTimeout(() => reject(new Error('超过5秒了')), 5000)
})
}
Promise.race([
ajax1(),
timeout()
]).then(res => {
console.log(res)
})
根据 Promise.race 特性,如果ajax1所请求的接口能在5秒内完成,then里的回调函数会返回请求所得的信息;如果5秒内不能完成,timeout将会执行然后跑出一个错误。
超时处理就完成了。
内容输出来源:拉勾大前端高薪训练营,以上文章中的内容根据老师讲课的语音和代码,结合自己的理解编辑完成。
标签:resolve,console,JavaScript,接口,并行执行,ajax,Promise,time 来源: https://blog.csdn.net/qiyuancoder/article/details/112103320