批量请求的应用场景
测试接口,批量查询快递信息,批量查询城市天气信息...
//以请求快递100为测试,先封装单个请求的函数
const axios = require("axios");
const Qs = require("qs");
const md5 = require("md5");
var key = "UWukdsvh3607"; //快递100给的key
var customer = "23CE1729F89970367F19E0366B067AA3"; //快递100给的customer
//查询京东快递单个请求的封装,传参数为订单号
const getJdOrderDetail = (num) => {
var param = { com: "jd", num: num };
var sign = md5(JSON.stringify(param) + key + customer).toUpperCase();
var data = { customer, sign, param: JSON.stringify(param) };
return axios({
url: "http://poll.kuaidi100.com/poll/query.do",
method: "post",
headers: { "Content-Type": "application/x-www-form-urlencoded" },
data: Qs.stringify(data),
});
};
- Promise.all的方式请求
const batchQuery = (numList) => {
const requests = numList.map((item, index) => {
return getJdOrderDetail(item);
});
return Promise.all(requests);
};
const numList = [
"JD0004885123331",
"JD0004885123332",
"JD0004885123333",
"JD0004885123336", //只有这条是帧数据
];
batchQuery(numList)
.then((res) => {
res.forEach((item) => {
console.log("查询结果是:", item.data.message);
});
})
.catch((err) => {
console.log("查询错误:" + err);
});
Promise.all优点是所有请求是同一时间发出的,能大大的提升请求响应时间。缺点是只有在所有请求都resolve的时候,才会在then里返回结果,否则只要有一个错误,那么就会进入到catch。 在这个快递批量请求中,实际上接口也有限制。当大批量地、高频率地、重复性请求接口时,会触发快递100的风控,限制访问。
- async await的请求方式
const sleep = (time) => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve();
}, time);
});
};
const batchQuery = async (numList) => {
let result = [];
for (let i = 0; i < numList.length; i++) {
try {
// 可以在这里增加flag,用于退出循环的按钮
const res = await getJdOrderDetail(numList[i]);
result.push("查询结果是" + res.data.message);
await sleep(1000);
} catch (e) {
result.push(e);
}
}
return result;
};
按顺序的逐个请求,并且每个请求有等待时间,可以增加退出循环按钮,不会引起接口频繁。
- 嵌套请求
let i = 0;
const numList = [
"JD0004885123331",
"JD0004885123332",
"JD0004885123333",
"JD0004885123336", //只有这条是帧数据
];
const batchQuery = () => {
// 可以在这里添加flag,退出循环的按钮
if (i < numList.length) {
getJdOrderDetail(numList[i++]).then((res) => {
setTimeout(() => {
batchQuery();
}, 1000);
});
}
};
效果和async await一样。