【问题标题】:slowness in promise chain承诺链缓慢
【发布时间】:2018-04-12 19:23:56
【问题描述】:

我的代码将大量文件从一个云存储传输到另一个云存储(同一区域)。工作流程是下载源文件流,然后将流上传到目标存储。

如果在 non-promise 循环中运行它们,传输速度很快(比如 100M/s),但会达到内存限制。最后服务器崩溃。

如果在promise链中,即在上一个作业完成后运行下一个作业,crash问题解决了,但是传输速度很慢(比如10M/s)。

我的问题:为什么承诺会影响下载和上传速度?还是我错过了什么?

代码sn-p:

transferArray.forEach(function (eachTransfer) { 
      queue = queue.then(function(result){
        // put result somewhere
        return eachFileTransfer(jobId,userid,eachTransfer);
      });  
    }); 
    queue.then(function(){
      console.log('done');
    });

我正在考虑使用带有并发的 PromisePool,但不确定速度会提高多少,以及我应该设置的合理数量的并发。参考帖子: Execute promises concurrently with a buffer pool size in Javascript

【问题讨论】:

  • 您是同时运行它们还是一个接一个地运行它们?一个原因是10 * 100M/s * 11 * 1000M/s * 10。池的大小将取决于情况。
  • 没有任何代码,我们都会猜测。我的猜测是,promise 链一次运行一个,而 for 循环同时运行一堆传输——最终试图运行太多。
  • “我正在考虑将 PromisePool 与并发一起使用” 很可能是答案。将并发设置为您希望同时运行的传输次数(根据您的问题,可能是 10)。
  • 谢谢你们!我的代码 sn-p 已发布。我认为你是对的,原生速度就是这样,但是在非承诺模式下,所有的都是一起运行的,所以我认为原生速度很快..我会尝试使用 PromisePool

标签: javascript promise es6-promise


【解决方案1】:

因为我猜你的循环会并行运行很多请求,这会更快(但也会超过各种限制)。因此,正如您所说,使用多个承诺链:

  const inParallel = 10;
  const promises = (new Array(inParallel)).fill(Promise.resolve());

  for(const [index, transfer] of transferArray.entries())
    promises[index % inParallel] = promises[index % inParallel].then(() =>  eachFileTransfer(jobId,userid,eachTransfer));

【讨论】:

  • 这假设所有传输都需要相同的时间。否则,您会在接近尾声时看到显着放缓,此时只有“较慢”的链仍在运行。
  • 是的,看起来还是很慢,而且只有一次传输正在运行。但无论如何,谢谢 Jonas W. 可能我的用法有问题。将检查并尝试使用 Bergi 推荐的内容。
  • @xiadong 只需使用 PromisePool 模块,这正是 bergi 推荐的
【解决方案2】:

最后,我通过 PromisePool 让它工作了。下面的代码sn-p是基于另一篇帖子:Execute promises concurrently with a buffer pool size in Javascript

由于我的代码比这篇文章相对复杂,认为它可能对其他人有所帮助:

var PromisePool = require('es6-promise-pool'); 

//single promises
function p1(){
  return new Promise(function(resolve, reject) {
      console.log('p1');  
      setTimeout(resolve, 2000, 'foo');
 });
}
function p2(){
  return new Promise(function(resolve, reject) {
      console.log('p2');  
      setTimeout(resolve, 2000, 'foo');
  });
}
function p3(){
 return new Promise(function(resolve, reject) {
    console.log('p3');  
    setTimeout(resolve, 2000, 'foo');
 });
}


var tasks=[];
var loopIndex = 0;
[1,2,3,4,5,6,7,8].forEach(function(v,i){

   console.log(v,i);

   //build promise chain
   var x = (v) => new Promise(function(resolve, reject) {
      console.log(v);

      p1().then(function(r){
         return p2();
      })
      .then(function(r){
        return p3();
      })
      .then(function(r){
        //console.log('embedded chain done');
        resolve('embedded chain done');
       }).catch(function(e){
        reject('embedded chain failed');
     }); 
    //setTimeout(resolve, 2000, 'foo');
  })

  //build one promise task
  tasks.push({fun:x,param:i});

  if(++loopIndex == 8){
     //once the array is done
    const promiseProducer = () => {
        while(tasks.length) {
           console.log('processing ');
           const task = tasks.shift();
           return task.fun(task.param);  
        } 
        return null;
     }

      // concurrent Promises set to 3
      const pool = new PromisePool(promiseProducer, 3); 
     //start to promise all, yet with concurrent 3 tasks.
     const poolPromise = pool.start(); 
     poolPromise.then(() => { console.log('done!'); })
    }  

});

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-11-28
    • 1970-01-01
    • 1970-01-01
    • 2012-07-17
    • 2015-11-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多