多次请求订单数据再存入数据库的思路:https://ourcoders.com/thread/show/7909/
控制并发的方法原文:https://segmentfault.com/a/1190000016389127?utm_source=tag-newest

思路

  1. 先给平台发一个请求,获得 count
  2. 根据 count 和我的 pageSize 来判定需要多少个请求
  3. 组装所有的请求,合并成一个 Array
  4. 使用 Promise.all(Array) 来进行处理
  5. 最后对结果数据进行下处理,然后同步到数据库
  6. 这时候考虑一个场景:如果你的promises数组中每个对象都是http请求,或者说每个对象包含了复杂的调用处理。而这样的对象有几十万个。那么会出现的情况是,你在瞬间发出几十万http请求(tcp连接数不足可能造成等待),或者堆积了无数调用栈导致内存溢出。这时候,我们就需要考虑对Promise.all做并发限制。

核心代码

  1. const asyncPool = (poolLimit, array, iteratorFn) => {
  2. let i = 0;
  3. const ret = [];
  4. const executing = [];
  5. const enqueue = function () {
  6. // 边界处理,array为空数组
  7. if (i === array.length) {
  8. return Promise.resolve();
  9. }
  10. // 每调一次enqueue,初始化一个promise
  11. const item = array[i++];
  12. const p = Promise.resolve().then(() => iteratorFn(item, array));
  13. // 放入promises数组
  14. ret.push(p);
  15. // promise执行完毕,从executing数组中删除
  16. const e = p.then(() => executing.splice(executing.indexOf(e), 1));
  17. // 插入executing数字,表示正在执行的promise
  18. executing.push(e);
  19. // 使用Promise.rece,每当executing数组中promise数量低于poolLimit,就实例化新的promise并执行
  20. let r = Promise.resolve();
  21. if (executing.length >= poolLimit) {
  22. r = Promise.race(executing);
  23. }
  24. // 递归,直到遍历完array
  25. return r.then(() => enqueue());
  26. };
  27. return enqueue().then(() => Promise.all(ret));
  28. }

页码page字段计算函数,用数组形式传入

  1. // 并发请求中,多次请求的参数用数组传入,此处只有pge加1,其他参数不变,所以用该方法生成page的数组
  2. const generateArray = (start, end) => {
  3. return Array.from(new Array(end + 1).keys()).slice(start)
  4. }

调用

  1. const times = Math.ceil(total / SIZE); // 需要查询的次数、一共查询多少页
  2. const reqFun = async i => {
  3. params.page = i;
  4. const result = await request(url, params, opts);
  5. return result.msg.records; // records是第三方的list参数
  6. };
  7. return asyncPool(CONCURRENT_COUNT, generateArray(1, times), reqFun).then(resp => {
  8. for (let r = 0; r < resp.length; r++) {
  9. const o = resp[r];
  10. list = list.concat(o);
  11. }
  12. // 将list存入数据库
  13. });