同步遍历调用异步请求
业务场景:一次性发送多个http请求,并且这些请求有先后顺序之分。
异步调用用单个http请求
// mock http 请求,并且服务器响应了请求
function mockRequest(requestBody, delayTime) {
return new Promise(resolve => {
setTimeout(function () {
// 随意resolve一个json即可
resolve({
statusCode: 200,
requestId: Math.random().toString().split('.').join(''),
data: requestBody
})
}, delayTime || 0)
})
}
// 简单的这样调用是不够的,因为是异步请求,我们需要一个回调函数(call back)
mockRequest({
id: '000',
query: 'a'
}, 1000)
async function getSilgleRequestData () {
const res = await mockRequest({
id: '000',
query: 'a'
}, 2000)
if (res && res.statusCode === 200) {
console.log(res) // { statusCode: 200, requestId: '00896521783396853', data: { id: '000', query: 'a' } }
}
}
getSilgleRequestData()
实际开发中比较常用的单个调用http请求我们已经实现了,那么也有在项目中一次操作(或者叫事件)触发多个请求,如果接口之间没有依赖关系,一般都是并发执行发送请求的。
异步并行调用多个http请求
// 仍然保留之前定义的 mockRequest
// 第一条接口
async function getRequestA () {
const res = await mockRequest({
id: '00A',
type: 'getRequestA'
}, 2000)
if (res && res.statusCode === 200) {
return res
}
}
// 第二条接口
async function getRequestB () {
const res = await mockRequest({
id: '00B',
type: 'getRequestB'
}, 1000)
if (res && res.statusCode === 200) {
return res
}
}
async function getMutilRequestData () {
console.time()
const resA = await getRequestA()
const resB = await getRequestB()
console.timeEnd() // 输出为??
if (resA.statusCode === 200) {
console.log(resA)
}
if (resB.statusCode === 200) {
console.log(resB)
}
}
getMutilRequestData()
因为上述两条api没有依赖关系,所以我们可以这些写:
const resA = await getRequestA()
const resB = await getRequestB()
如果是有依赖关系的话——getRequestA
的**响应数据(response data)会被getRequestB
作为请求参数(request data)**使用,那么应该这样做:
const resA = await getRequestA()
if (resA.statusCode === 200) {
const resB = await getRequestB(resA.data.id)
if (resB.statusCode === 200) {
console.log(resB)
}
}
同步遍历中发送异步http请求
所以结合以上所有,我们需要一次性发送多条api,有顺序的要求,那么我们可以定义一个数组,这个数组的每个元素都是请求参数,循环此数组,使用递归函数的方式调用api请求。
// ... mockRequest
// 递归函数,遍历requestList元素,依次发送请求,当前请求响应成功后才会发送下一个请求
async function getData (requestList, callback, i = 0) {
let delayTime = 0
const res = await mockRequest(requestList[i], delayTime+=1000)
if (res && res.statusCode === 200) {
callback(res)
if (++i < requestList.length) {
getData(requestList, callback, i)
}
}
}
// 定义请求参数,每一个元素都是一次请求,元素的内容都是请求参数
const requestList = [
{
id: '001',
query: 'x'
},
{
id: '002',
query: 'y'
},
{
id: '003',
query: 'z'
}
]
getData(requestList, function (res) {
console.log(res)
})
更多
这只是一个比较简陋的实现方案,并非最佳实践。比如此回调是每次请求成功的回调,有些业务场景需要全部请求完成后执再执行回调,还有这是依次发送请求的,也可以实现一个并行请求的方式,更多的扩展功能不再讲述。