微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

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将会执行然后跑出一个错误

超时处理就完成了。

内容输出来源:拉勾大前端高薪训练营,以上文章中的内容根据老师讲课的语音和代码,结合自己的理解编辑完成。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。

相关推荐