2012-03-02 14 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 –

答えて

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

上記の答え、RE:NPMのasyncは最良の答えですが、制御フローの詳細を学ぶしたい場合:


コントロールフローパターンを調べる必要があります。 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'の値が期待値を含んでいないことに気付きました。例えば 'console.log(file)'は同じファイルを10回印刷します最初の10行( 'limit'の値が10の場合) – golimar

62

、私はCaolanマクマホンの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

1

他の人の答えが古くなっているようです。これはparalleLimitasyncから簡単に解決できます。使用方法は次のとおりです。私はそれをテストしていない。

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

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

は、キュー関数とパラレル行列の間に違いがありますか? – lizlalala