2012-03-02 3 views
40

J'ai une application Node.js qui obtient une liste de fichiers localement et les télécharge sur un serveur. Cette liste pourrait contenir des milliers de fichiers.Limiter les appels asynchrones dans Node.js

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

Si je utiliser cette fonction sur des milliers de fichiers, upload_file sera appelé des milliers de fois à la fois, et meurent le plus probable (ou lutte au moins). Dans le monde synchrone, nous créerions un pool de threads et le limiterions à un certain nombre de threads. Existe-t-il un moyen simple de limiter le nombre d'appels asynchrones exécutés en même temps?

+0

Une limite similaire, mais le taux (par seconde/minute) est ici: https://stackoverflow.com/questions/20253425/throttle-and-queue-up-api-requests-due-to-per- second cap –

Répondre

6

Vous devriez essayer de faire la queue. Je suppose qu'un rappel est déclenché lorsque upload_file() se termine. Quelque chose comme ça devrait faire l'affaire (non testé):

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

La réponse ci-dessus, re: async sur NPM est la meilleure réponse, mais si vous souhaitez en savoir plus sur le flux de contrôle:


Vous devriez regarder dans les modèles de flux de contrôle. Il y a une discussion merveilleuse sur les modèles de flux de contrôle dans Chapter 7 of Mixu's Node Book. À savoir, je regarderais l'exemple dans 7.2.3: Limited parallel - une simultanéité simultanée asynchrone limitée pour la boucle.

J'ai adapté son exemple:

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

Cela fonctionne correctement et n'exécute que le nombre spécifié d'opérations async; cependant, j'ai remarqué que la valeur de 'file' dans' doUpload' (par exemple avant 'running -;') ne contient pas la valeur attendue, par exemple 'console.log (fichier)' va imprimer le même fichier 10 fois les 10 premières lignes (si 'limite' a une valeur de 10, c'est-à-dire) – golimar

62

Comme d'habitude, je vous recommande de async module Caolan McMahon.

Faites votre fonction upload_file prendre un rappel car il est second paramètre:

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

C'est la bonne façon de faire les choses. – Tyguy7

1

Les réponses des autres semblent être dépassées. Cela peut être résolu facilement en utilisant paralleLimit de async. Voici comment l'utiliser. Je ne l'ai pas testé.

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

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

Y a-t-il une différence entre la fonction de file d'attente et la parallellimité? – lizlalala

Questions connexes