4

我的问题基本上是

我知道Promise.allSettled,但我没有找到一种同时限制并发的好方法。

到目前为止我所拥有的:

想法1使用p-limit

const pLimit = require('p-limit');
const limit = pLimit(10);

let promises = files.map(pair => {
    var formData = {
        'file1': fs.createReadStream(pair[0]),
        'file2': fs.createReadStream(pair[1])
    };
        
    return limit(() => uploadForm(formData));
});
    
(async () => {
    const result = await Promise.allSettled(promises).then(body => {
        body.forEach(value => {
            if(value.status == "rejected")
                file.write(value.reason + '\n---\n');
        });
    });
})();

我对这个解决方案的问题是,我必须首先创建所有承诺,并为每个承诺打开两个文件流,我将达到打开文件的限制。

想法 2使用p-queue:我尝试使用生成器函数在queue.on 'next'事件中创建和添加新的 Promise,但我无法让它正常工作,这可能不是这项工作的正确工具。

使用 PromisePool 的想法 3:这在开始时看起来很有希望。其中一些支持生成器函数来为池创建承诺,但我找不到一个明确声明其行为类似于Promise.allSettled.

我实施es6-promise-pool只是为了发现它会在第一次承诺拒绝后停止。

4

2 回答 2

5

自己实现它很简单——创建一个函数数组,在调用时返回 Promise。然后实现一个限制器函数,该函数从该数组中获取函数并调用它们,一旦完成,再次递归调用限制器,直到数组为空:

const request = (file) => new Promise((res, rej) => {
  console.log('requesting', file);
  setTimeout(() => {
    if (Math.random() < 0.5) {
      console.log('resolving', file);
      res(file);
    } else {
      console.log('rejecting', file);
      rej(file);
    }
  }, 1000 + Math.random() * 1000);
});
const files = [1, 2, 3, 4, 5, 6];

const makeRequests = files.map(file => () => request(file));
const results = [];
let started = 0;
const recurse = () => {
  const i = started++;
  const makeRequest = makeRequests.shift();
  return !makeRequest ? null : Promise.allSettled([makeRequest()])
    .then(result => {
      results[i] = result[0];
      return recurse();
    })
};
const limit = 2;
Promise.all(Array.from({ length: limit }, recurse))
  .then(() => {
    console.log(results);
  });

如果结果的顺序无关紧要,可以通过删除startedi变量来简化。

于 2020-11-20T15:18:41.783 回答
1

接受的答案或多或少像p-limit. 您遇到了问题,p-limit因为流是在限制回调之外声明的。

这将解决您的问题:

let promises = files.map(pair => {  
    return limit(() => uploadForm({
        'file1': fs.createReadStream(pair[0]),
        'file2': fs.createReadStream(pair[1])
    }));
});
于 2021-08-30T07:27:47.523 回答