2014-11-18 25 views
7

Có cách nào để giới hạn số lượng đồng thời Q hứa hẹn sẽ được thực hiện cùng một lúc trong nút js không?Giới hạn Q lời hứa đồng thời trong Node js

Tôi đang xây dựng một trình gỡ rối web, yêu cầu và phân tích hơn 3000 trang và không cần điều chỉnh một số yêu cầu mà tôi đưa ra không được trả lời đúng thời gian, vì vậy kết nối sẽ nằm và phản hồi cần thiết (mã html) không có sẵn.

Để phản tác vụ này, tôi thấy rằng việc hạn chế số lượng yêu cầu mà sự cố của tôi biến mất.


Tôi đã thử các phương pháp sau đây nhưng không có kết quả:

tôi cần phải yêu cầu một loạt các url, chỉ thực hiện 1 yêu cầu tại một thời điểm và khi tất cả các url trong mảng đã hoàn thành, sau đó trả lại kết quả trong một mảng.

function processWebsite() { 
    //computed by this stage 
    urls = [u1,u2,u3,u4,l5,u6,u7,u8,u9]; 

    var promises = throttle(urls,1,myfunction); 

    // myfunction returns a Q promise and takes a considerable 
    // amount of time to resolve (approximately 2-5 minutes) 

    Q.all(promises).then(function(results){ 
     //work with the results of the promises array 
    }); 
} 

Trả lời

0

Bạn có thể yêu cầu một url mới trong một khối then()

myFunction(urls[0]).then(function(result) { 
    myFunction(urls[1]).then(function(result) { 
    myFunction(urls[2]).then(function(result) { 
     ... 
    }); 
    }); 
}); 

Tất nhiên, đây sẽ là hành vi năng động của nó. Tôi sẽ mantain một hàng đợi và dequeue một url duy nhất một khi một lời hứa được giải quyết. Sau đó thực hiện một yêu cầu khác. Và có lẽ có một đối tượng băm liên quan đến các kết quả.

Một mất thứ hai:

var urls = ...; 
var limit = ...; 
var dequeue = function() { 
    return an array containing up to limit 
}; 

var myFunction = function(dequeue) { 
    var urls = dequeue(); 

    $q.all(process urls); 
}; 

myFunction(dequeue).then(function(result) { 
    myFunction(dequeue).then(function(result) { 
    myFunction(dequeue).then(function(result) { 
     ... 
    }); 
    }); 
}); 
+0

Tôi nghĩ đến một cái gì đó tương tự, nhưng điều này dường như đánh bại mục đích của lời hứa, nó có cấu trúc rất giống với gọi lại chuẩn trong JavaScript. Ngoài ra tôi không thể dễ dàng chỉ định một đồng tiền tối đa lớn hơn 1 với kiểu mã này. Không có giải pháp loại Q-lời hứa ga? – user3438286

+0

tôi nghĩ rằng một phiên bản chung là đạt được. Tôi chỉnh sửa câu trả lời của tôi. Một lời hứa Q-ga sẽ hoạt động theo cách này, tôi nghĩ vậy. –

+0

Cảm ơn bạn, tôi nghĩ rằng tôi có thể làm việc từ đây – user3438286

2

Tôi muốn làm điều này, điều này sẽ lặp qua mỗi URL, xây dựng một chuỗi những lời hứa mà chạy khi trước đó kết thúc, và giải quyết với một mảng của các kết quả theo yêu cầu .

return urls.reduce(function(acc, url){ 
    return acc.then(function(results) 
     return myfunction(url).then(function(requestResult){ 
      return results.concat(requestResult) 
     }); 
    }); 
}, Q.resolve([])); 

Bạn có thể biến chúng thành một helper quá:

var results = map(urls, myfunction); 

function map(items, fn){ 
    return items.reduce(function(acc, item){ 
     return acc.then(function(results) 
      return fn(item).then(function(result){ 
       return results.concat(result) 
      }); 
     }); 
    }, Q.resolve([]) 
} 

Lưu ý, thư viện hứa bluebird có một helper để đơn giản hóa loại điều.

return Bluebird.map(urls, myfunction, {concurrency: 1}); 
+0

Cảm ơn rất nhiều về liên kết đến thư viện lời hứa, dự án sử dụng q lời hứa và tại thời điểm nó quá lớn để thay đổi thư viện hứa hẹn, nhưng bệnh sử dụng này cho các dự án trong tương lai;) – user3438286

+1

Yup, đó là lý do tại sao tôi đã đưa ra các tùy chọn cho cả hai: D – loganfsmyth

1

Đây là đâm của tôi lúc thực hiện một Throttled map chức năng cho Q.

function qMap(items, worker, concurrent) { 
    var result = Q.defer(); 
    var work = []; 
    var working = 0; 
    var done = 0; 

    concurrent = parseInt(concurrent, 10) || 1; 

    function getNextIndex() { 
     var i; 
     for (i = 0; i < items.length; i++) { 
      if (typeof work[i] === "undefined") return i; 
     } 
    } 
    function doneWorking() { 
     working--; 
     done++; 
     result.notify(+((100 * done/items.length).toFixed(1))); 
     if (!startWorking() && done === items.length) { 
      result.resolve(work); 
     } 
    } 
    function startWorking() { 
     var index = getNextIndex(); 
     if (typeof index !== "undefined" && working < concurrent) { 
      working++; 
      work[index] = worker(items[index]).finally(doneWorking); 
      return true; 
     } 
    } 
    while (startWorking()); 
    return result.promise; 
} 

Nó chấp nhận

  • một mảng của items để làm việc trên (URL, trong trường hợp của bạn),
  • a worker (phải là chức năng chấp nhận một mục và trả lời lời hứa)
  • và giá trị tối đa là concurrent mục để hoạt động tại bất kỳ thời điểm đã định nào.

Nó trả

  • một lời hứa và
  • giải quyết một loạt các lời hứa giải quyết khi tất cả các công nhân đã hoàn thành.

Nó không thất bại, bạn phải kiểm tra các lời hứa cá nhân để xác định trạng thái tổng thể của hoạt động.

Trong trường hợp của bạn, bạn sẽ sử dụng nó như thế, ví dụ với 15 yêu cầu đồng thời:

// myfunction returns a Q promise and takes a considerable 
// amount of time to resolve (approximately 2-5 minutes) 

qMap(urls, myfunction, 15) 
.progress(function (percentDone) { 
    console.log("progress: " + percentDone); 
}) 
.done(function (urlPromises) { 
    console.log("all done: " + urlPromises); 
}); 
Các vấn đề liên quan