优雅的Promise并发处理及错误重试

449 阅读1分钟

需求背景 ⛰️

目前在学习NodeJs过程中,刚好有个需求需要调用第三方接口拉取几千条详情数据,意味着需要发起几千个请求,如果全部请求同时发出,那将出现大量失败的请求。此时我需要对这些请求做并发限制,并且当出现接口错误时对请求进行错误重试,从而达到尽可能完整的获取这几千条数据。

上代码

// 并发处理库
const { PromisePool } = require('@supercharge/promise-pool');
// 错误重试库
const promiseRetry = require('promise-retry')

/**
 * Mock用户数据
 */
const MOCK_USERS = [
  { name: 'Marcus' },
  { name: 'Norman' },
  { name: 'Christian' }
];

/**
 * 随机布尔值
 * @param {number} [trueRate=.5] 返回true的比率,默认50%
 * @returns {boolean} true 或 false
 */
const randomBoolean = (trueRate) => Math.random() > (1 - trueRate)

// Mock用户详情接口
const MockApiUserDetail = (data) => new Promise((resolve, reject) => setTimeout(() => {
  // 如果为"true",接口返回成功
  if (randomBoolean() === true) {
    resolve(data)
  } else {
    reject('error')
  }
}, 1000));

PromisePool
  // 设置并发数
  .withConcurrency(1)
  // 设置并发池需要的数据
  .for(MOCK_USERS)
  // 通过迭代项目开始处理承诺池,并通过异步“回调”函数运行每个项目
  .process(async (userData, index, pool) => {
    const userInfo = await promiseRetry((retry, attempt) => {
      console.log(`${userData.name}重试次数: ${attempt}`)
      return MockApiUserDetail(userData).catch(retry)
    }, {
      // 设置重试次数
      retries: 10
    })
    console.log(`请求${userData.name}成功 ${JSON.stringify(userInfo)}`)
    console.log('--------------')
    return userInfo
  })
  .then(({ results, errors }) => {
    console.log(`请求池结果 ${JSON.stringify(results)}`)
    console.log(`请求池错误 ${JSON.stringify(errors)}`)
  })