如何限制并发执行?

时间:2015-06-05 00:14:01

标签: javascript node.js request

我想下载70张图片。它们的完整尺寸约为100mb。

这是我简化的代码部分

function downloadImage(src){
    var dst = '...';
    request(src).pipe(fs.createWriteStream(dst));
    return dst;
}

arrayOf70.forEach(function(e){
    var thing = new Thing({
        // ...
        image: downloadImage(url)
    });
    thing.save();
}

问题是并发下载太多。好的第一步:通过一个巨大的超时请求。

request({url: src, timeout: 120000000}).pipe(fs.createWriteStream(dst));

嗯,由于它超过OS TCP超时,因此效果不佳。至少我认为这是问题所在。无论如何,我正在加时间连接

stream.js:94
      throw er; // Unhandled stream error in pipe.
            ^
Error: connect ETIMEDOUT
    at exports._errnoException (util.js:746:11)
    at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1000:19)

因此。限制并发下载量的方法是什么?

2 个答案:

答案 0 :(得分:1)

以下是setInterval的示例:

var array_length = arrayOf70.length;
var i = 0;

var request_interval = setInterval(makeRequest, 100);

function makeRequest()
   if(i<array_length){
      var thing = new Thing({
         // ...
         image: downloadImage(url)
      });
      thing.save();
      i++;
   }else{
      clearInterval(request_interval);
   }
},100);

答案 1 :(得分:1)

超时不是理想的解决方案。你真正需要的是等待下载完成的能力,然后立即开始新的下载。并且特定次数并行。 你可以通过使用回调来做到这一点。

function downloadImage(src, callback){
  var dst = '...';
  http.get(src, function(res) {
    res.pipe(fs.createWriteStream(dst))
      .on("finish", function() {
        callback(dst);
    });
  });
}    
function downloadAllImages(array) {
  var idx = 0;

  function downloadLoop() {
    if(idx >= array.length) return;
    downloadImage(array[idx++], function(dst) {
      var thing = new Thing({
          // ...
          image: dst
      });
      thing.save();
      downloadLoop();
    });
  }

  for(var i = 0; i < 5; i++) downloadLoop(); //start 5 concurrent download "loops"
}