关于批量请求接口的几种方式

4,766 阅读2分钟

批量请求的应用场景

测试接口,批量查询快递信息,批量查询城市天气信息...

//以请求快递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),
  });
};

  1. 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的风控,限制访问。

  1. 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;
};

按顺序的逐个请求,并且每个请求有等待时间,可以增加退出循环按钮,不会引起接口频繁。

  1. 嵌套请求
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一样。