2012-03-02 51 views
40

Tôi có ứng dụng Node.js nhận danh sách tệp cục bộ và tải chúng lên máy chủ. Danh sách này có thể chứa hàng nghìn tệp.Hạn chế các cuộc gọi không đồng bộ trong Node.js

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

Nếu tôi thực hiện điều này với hàng ngàn tệp, upload_file sẽ nhận được hàng nghìn lần cùng một lúc và rất có thể là chết (hoặc ít nhất là đấu tranh). Trong thế giới đồng bộ, chúng ta sẽ tạo một nhóm luồng và giới hạn nó thành một số luồng nhất định. Có cách nào đơn giản để giới hạn số lượng cuộc gọi không đồng bộ được thực hiện cùng một lúc không?

+0

Giới hạn tương tự nhưng tỷ lệ (mỗi giây/phút) là ở đây: https://stackoverflow.com/questions/20253425/throttle-and-queue-up-api-requests-due-to-per- nắp thứ hai –

Trả lời

6

Bạn nên thử xếp hàng. Tôi giả định rằng một cuộc gọi lại được kích hoạt khi kết thúc upload_file(). Một cái gì đó như thế này nên làm các trick (chưa được kiểm tra):

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

Câu trả lời ở trên, tái: async trên NPM là câu trả lời tốt nhất, nhưng nếu bạn muốn tìm hiểu thêm về dòng điều khiển:


Bạn nên xem xét các mẫu luồng kiểm soát. Có một cuộc thảo luận tuyệt vời về các mẫu điều khiển luồng trong Chapter 7 of Mixu's Node Book. Cụ thể là, tôi sẽ xem ví dụ trong 7.2.3: Song song giới hạn - một sự đồng bộ, song song, đồng thời được giới hạn cho vòng lặp.

Tôi đã thích nghi dụ của mình:

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

Nó hoạt động tốt và chỉ chạy số lượng hoạt động không đồng bộ được chỉ định; tuy nhiên tôi nhận thấy rằng giá trị của 'file' bên trong' doUpload' (ví dụ trước 'running -;') không chứa giá trị mong đợi, ví dụ 'console.log (file)' sẽ in cùng một tệp 10 lần trên 10 dòng đầu tiên (nếu 'giới hạn' có giá trị là 10, nghĩa là) – golimar

62

Như thường lệ, tôi khuyên bạn nên async module Caolan McMahon.

Make chức năng upload_file bạn hãy gọi lại vì nó là tham số thứ hai:

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

Đây là cách đúng để thực hiện. – Tyguy7

1

Những người khác câu trả lời dường như bị lỗi thời. Điều này có thể được giải quyết dễ dàng bằng cách sử dụng paralleLimit từ async. Dưới đây là cách sử dụng nó. Tôi chưa thử nghiệm nó.

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

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

có bất kỳ sự khác biệt nào giữa hàm xếp hàng và sai số không? – lizlalala

Các vấn đề liên quan