2012-03-02 76 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