2012-03-02 20 views
40

Tengo una aplicación Node.js que obtiene una lista de archivos localmente y los carga en un servidor. Esta lista podría contener miles de archivos.Limitación de llamadas asíncronas en Node.js

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

Si ejecuto esto con miles de archivos, upload_file se llamará miles de veces todos a la vez, y lo más probable morir (o por lo menos la lucha). En el mundo sincrónico, creamos un grupo de subprocesos y lo limitamos a un cierto número de subprocesos. ¿Existe alguna manera simple de limitar cuántas llamadas asíncronas se ejecutan a la vez?

+0

Un límite similar pero tasa (por seg/minuto) es aquí: https://stackoverflow.com/questions/20253425/throttle-and-queue-up-api-requests-due-to-per- segunda capa –

Respuesta

6

Debe intentar hacer cola. Supongo que se activa una devolución de llamada cuando finaliza upload_file(). Algo como esto debe hacer el truco (no probado):

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 respuesta anterior, re: async en la NGP es la mejor respuesta, pero si desea obtener más información sobre el flujo de control:


Debería observar los patrones de flujo de control. Hay una discusión maravillosa sobre los patrones de flujo de control en Chapter 7 of Mixu's Node Book. A saber, me gustaría ver el ejemplo en 7.2.3: paralelo limitado - una concurrencia asíncrona, paralela, limitada para el bucle.

he adaptado su ejemplo:

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

Funciona bien y solo ejecuta el número especificado de operaciones asincrónicas; sin embargo, noté que el valor de 'file' dentro de' doUpload' (por ejemplo, antes de 'running -;') no contiene el valor esperado, por ejemplo 'console.log (file)' imprimirá el mismo archivo 10 veces en las primeras 10 líneas (si 'limit' tiene un valor de 10, es decir) – golimar

62

Como de costumbre, recomiendo async module de Caolan McMahon.

Haga su función upload_file tomar una devolución de llamada, ya que es segundo parámetro:

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

Esta es la forma correcta de hacer las cosas. – Tyguy7

1

Las otras respuestas parecen ser obsoleta. Esto puede resolverse fácilmente usando paralleLimit desde async. A continuación se muestra cómo usarlo. No lo he probado.

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

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

¿hay alguna diferencia entre la función de cola y el paralelismo? – lizlalala

Cuestiones relacionadas