关于promise.all()的使用及说明

关于promise.all()的使用

Promise.all可以将多个Promise实例包装成一个新的Promise实例。

同时,成功和失败的返回值是不同的,成功的时候返回的是一个结果数组,而失败的时候则返回最先被reject失败状态的值。

关键代码:将所有异步操作存储到数组pros中,Promise.all(pros)执行所有异步操作

  1. let pros = []
  2. data.forEach(element => {
  3.      pros.push( this.getjsonFile(element.json,element.fileName) )
  4. });
  5. Promise.all(pros).then(val => {
  6.      this.fontsList = […val]
  7. })

示例:

  1. // 获取字体所有json文件展示
  2. getIconFonts(isFresh) {
  3.      req.post(window.context.uc+`/system/file/v1/queryIconFiles`).then(rep => {
  4.      if(rep && rep.data) {
  5.      // 将所有异步操作存储到数组pros中
  6.      let pros = []
  7.      data.forEach(element => {
  8.      pros.push( this.getJsonFile(element.json,element.fileName) )
  9.      });
  10.      // 执行所有异步操作后处理数据
  11.      Promise.all(pros).then(val => {
  12.      this.fontsList = […val]
  13.      this.uploadFonts = […this.fontsList]
  14.      })
  15.      }
  16.      });
  17. },
  18. // 通过id获取json文件
  19. getJsonFile(fileId, fileName) {
  20.      return new Promise((resolve, reject) => {
  21.      req.get(window.context.uc +‘/system/file/v1/preview?fileId=’ + fileId).then(rep => {
  22.      if(rep && rep.data) {
  23.      let data = {
  24.          fileName,
  25.          rep.data
  26.      }
  27.      // 返回处理后的数据
  28.      resolve(data)
  29.      }
  30.      })
  31.      })
  32. }

Promise.all实现限制并发请求函数

Promise.all 的简单解释

  1. // 当以下数组中promise1, promise2, promise3都resolve之后,触发promise.all的then函数。
  2. Promise.all([promise1, promise2, promise3]).then((values) => {
  3.      console.log(values);
  4. });

需求解释

所谓并发请求,即有待请求接口100个,限制每次只能发出10个。即同一时刻最多有10个正在发送的请求。

每当10个之中有一个请求完成,则从待请求的接口中再取出一个发出。保证当前并发度仍旧为10。

直至最终请求完成。

设计思路

简单思路如下:(假设并发请求函数名字为limitedRequest)

  • 设定一个数组(命名为:pool),用于后续Promise.all的使用
  • 当limitedRequest被调用的时候,首先一次性发出10个请求,并放入到pool中
  • 每一个请求完成后的回调函数中继续触发下一个请求,而下一个请求返回Promise,他的回调函数继续绑定同样的回调函数,即循环调用。(看不懂就直接看代码更易懂)
  • 直到全部请求完成,停止。

代码实现

具体代码如下

  1. // 模仿一个fetch的异步函数,返回promise
  2. function mockFetch(param) {
  3.      return new Promise((resovle) => {
  4.      setTimeout(() => {
  5.      resovle(param);
  6.      }, 2000);
  7.      });
  8. }
  9.  
  10. function limitedRequest(urls, maxNum) {
  11.      const pool = [];
  12.      // 处理maxNum比urls.length 还要大的情况。
  13.      const initSize = Math.min(urls.length, maxNum);
  14.      for (let i = 0; i < initSize; i++) {
  15.      // 一次性放入初始的个数
  16.      pool.push(run(urls.splice(0, 1)));
  17.      }
  18.      // r 代表promise完成的resolve回调函数
  19.      // r 函数无论什么样的结果都返回promise,来确保最终promise.all可以正确执行
  20.      function r() {
  21.      console.log(‘当前并发度:’, pool.length);
  22.      if (urls.length === 0) {
  23.      console.log(‘并发请求已经全部发起’);
  24.      return Promise.resolve();
  25.      }
  26.      return run(urls.splice(0, 1));
  27.      }
  28.      // 调用一次请求
  29.      function run(url) {
  30.      return mockFetch(url).then(r);
  31.      }
  32.      // 全部请求完成的回调
  33.      Promise.all(pool).then(() => {
  34.      console.log(‘请求已经全部结束’);
  35.      });
  36. }
  37. // 函数调用
  38. limitedRequest([1, 2, 3, 4, 5, 6, 7, 8], 3);

# 最终返回结果
$ node .\src\views\doc\detail\index.js
当前并发度: 3
当前并发度: 3
当前并发度: 3
当前并发度: 3
当前并发度: 3
当前并发度: 3
并发请求已经全部发起
当前并发度: 3
并发请求已经全部发起
当前并发度: 3
并发请求已经全部发起
请求已经全部结束

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。

标签

发表评论