【node实战系列】异步并发,自定义Promise.allSettled

avatar
前端开发工程师 @bigo

file

本文首发于:github.com/bigo-fronte… 欢迎关注、转载。

背景

bigo前端开始推广bff,hello农场作为首个bff落地项目,历经2个月,完成了从0-1的落地实践。

【node实战系列】按照小模块拆分,从开发者的角度讲叙,如何进行bff高可用编码。

本系列文章,基于eggjs框架编码,使用ts语法,为了提升阅读体验,建议大家先了解一下eggjs。

系列文章

欢迎大家关注我们的github blog,持续更新。 github.com/bigo-fronte…

请求并发

由于nodejs事件循环的实现,让异步编程变得简单。

我们可以直接使用Promise对象进行异步调用。bff的一个核心场景就是接口聚合,自然离不开多个接口并发请求。

请求并发可以让我们把请求时间缩短为当前最长请求的时间。

举个例子:需要聚合a、b、c三个接口,对应的接口响应时间为100ms、150ms、200ms,如果是顺序请求,聚合耗时450ms, 但是使用请求并发,聚合耗时200ms,收益是十分明显的。

Promise.allSettled

Promise.all:短路特性,有一个请求错误,直接走catch,不再走then。 Promise.allSettled : 无论请求对错最终都会返回一个数组对象到then中,并切返回的数据中标识了错误跟正确数据的区别。 但是属于新的提案,有需要nodejs>=12.9.0,我们的测试环境还使用v10版本,所以需要我们手动封装一下。

image.png

自定义Promise.allSettled

实现

// 请求并发,相当于Promise.allSettled
allSettled(promises) { // 自定义 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/allSettled
  return new Promise(resolve => {
    const data: any = [], len = promises.length;
    let count = len;
    for (let i = 0; i < len; i += 1) {
      const promise = promises[i];
      promise.then(res => {
        data[i] = res;
      }, error => {
        data[i] = error;
      }).finally(() => { // promise has been settled
        if (!--count) {
          resolve(data);
        }
      });
    }
  });
}

业务使用示例

const resList = await ctx.helper.allSettled([
  // 1.我的农场信息
  service.accounts.getAccountInfoByUid.request(),
  // 2.用户信息
  service.accounts.getUserExtraInfo.requestByUid(),
  // 3.是否大客户
  service.accounts.getBigClient.request(),
  // 4.是否显示礼包红点
  service.gift.checkAppTabIsNeedShowRedPoint.request(),
  // 5.今天是否签到
  service.task.signHistory.isSignedToday(),
  // 6.个人形象集合
  service.accounts.getAccountAppearanceInfo.getAppearanceList(),
  // 7.我的形象
  service.accounts.getAccountAppearanceInfo.appearanceInfo(),
  // 8.礼包列表
  service.gift.getGiftList.request(),
  // 9.任务红点
  service.task.listCommonTask.isShowTaskRedPoint()
]);

小结

综上,一个简单又实用的请求并发功能就实现了。

欢迎大家留言讨论,祝工作顺利、生活愉快!

我是bigo前端,下期见。