2012-03-02 63 views
40

我有一个Node.js应用程序,它可以在本地获取文件列表并将它们上载到服务器。该列表可能包含数千个文件。限制Node.js中的异步调用

for (var i = 0; i < files.length; i++) { 
    upload_file(files[i]); 
} 

如果我执行此与成千上万的文件,upload_file将被调用数千次全部一次,最有可能的模具(或至少斗争)。在同步世界中,我们将创建一个线程池并将其限制到一定数量的线程。有没有简单的方法来限制同时执行多少个异步调用?

+0

类似但速率限制(每秒/分钟)是在这里:https://stackoverflow.com/questions/20253425/throttle-and-queue-up-api-requests-due-to-per- second-cap – 2017-12-04 06:33:32

回答

6

您应该尝试排队。我假设当upload_file()完成时会触发回调。这样的事情应该做的伎俩(未经测试):

function upload_files(files, maxSimultaneousUploads, callback) { 
    var runningUploads = 0, 
     startedUploads = 0, 
     finishedUploads = 0; 

    function next() { 
     runningUploads--; 
     finishedUploads++; 

     if (finishedUploads == files.length) { 
      callback(); 
     } else { 
      // Make sure that we are running at the maximum capacity. 
      queue(); 
     } 
    } 

    function queue() { 
     // Run as many uploads as possible while not exceeding the given limit. 
     while (startedUploads < files.length && runningUploads < maxSimultaneousUploads) { 
      runningUploads++; 
      upload_file(files[startedUploads++], next); 
     } 
    } 

    // Start the upload! 
    queue(); 
} 
19

上面的答案,回复:async上NPM是最好的答案,但如果你想了解更多关于控制流程:


你应该看看控制流模式。关于Chapter 7 of Mixu's Node Book中的控制流模式有一个很好的讨论。也就是说,我会看7.2.3中的例子:有限的并行 - 一个异步,并行,并发限制的循环

我已经适应他的例子:

function doUpload() { 
    // perform file read & upload here... 
} 

var files = [...]; 
var limit = 10;  // concurrent read/upload limit 
var running = 0;  // number of running async file operations 

function uploader() { 
    while(running < limit && files.length > 0) { 
     var file = files.shift(); 
     doUpload(file, function() { 
      running--; 
      if(files.length > 0) 
       uploader(); 
     }); 
     running++; 
    } 
} 

uploader(); 
+0

它工作正常,只运行指定数量的异步操作;但是我注意到'doUpload'内的'file'的值(例如在'running - ;'之前)不包含期望的值,例如'console.log(file)'会在同一个文件上打印10次前10行(如果'limit'的值是10,那就是) – golimar 2016-04-18 15:58:29

62

像往常一样,我建议Caolan McMahon的async module

让您upload_file功能需要一个回调,因为它的第二个参数:

var async = require("async"); 

function upload_file(file, callback) { 
    // Do funky stuff with file 
    callback(); 
} 

var queue = async.queue(upload_file, 10); // Run ten simultaneous uploads 

queue.drain = function() { 
    console.log("All files are uploaded"); 
}; 

// Queue your files for upload 
queue.push(files); 

queue.concurrency = 20; // Increase to twenty simultaneous uploads 
+1

这是正确的做事方式。 – Tyguy7 2015-10-29 22:44:59

1

其他人的答案似乎已经过时。这可以通过使用paralleLimitasync轻松解决。以下是如何使用它。我没有测试过它。

var tasks = files.map(function(f) { 
    return function(callback) { 
     upload_file(f, callback) 
    } 
}); 

parallelLimit(tasks, 10, function(){ 
}); 
+3

队列函数和并行限制之间有什么区别吗? – lizlalala 2017-05-26 06:06:22