[英]How can I limit Q promise concurrency?
如何編寫限制Q promise並發的方法?
例如,我有一個方法spawnProcess
。 它返回一個Q承諾。
我希望一次生成的進程不超過5個,但對調用代碼透明。
我需要實現的是一個帶簽名的函數
function limitConcurrency(promiseFactory, limit)
我可以這樣打電話
spawnProcess = limitConcurrency(spawnProcess, 5);
// use spawnProcess as usual
我已經開始研究我的版本,但我想知道是否有人有一個我可以檢查的簡潔實現。
我有一個庫為你做這個https://github.com/ForbesLindesay/throat
您可以通過browserify使用它或從brcdn( https://www.brcdn.org/?module=throat&version=latest )下載獨立版本並將其添加為腳本標記。
然后(假設Promise
構造函數是polyfilled或在您的環境中實現),您可以:
//remove this line if using standalone build
var throat = require('throat');
function limitConcurrency(promiseFactory, limit) {
var fn = throat(promiseFactory, limit);
return function () {
return Q(fn.apply(this, arguments));
}
}
你可以直接調用throat(promiseFactory, limit)
,但這會返回一個promise promise而不是一個Q promise。
我也非常喜歡將它與array.map一起使用。
// only allow 3 parallel downloads
var downloadedItems = Q.all(items.map(throat(download, 3)));
這似乎對我有用。
我不確定我是否可以簡化它。 scheduleNextJob
的遞歸是必要的,因此running < limit
和limit++
總是在相同的tick中執行。
'use strict';
var Q = require('q');
/**
* Constructs a function that proxies to promiseFactory
* limiting the count of promises that can run simultaneously.
* @param promiseFactory function that returns promises.
* @param limit how many promises are allowed to be running at the same time.
* @returns function that returns a promise that eventually proxies to promiseFactory.
*/
function limitConcurrency(promiseFactory, limit) {
var running = 0,
semaphore;
function scheduleNextJob() {
if (running < limit) {
running++;
return Q();
}
if (!semaphore) {
semaphore = Q.defer();
}
return semaphore.promise
.finally(scheduleNextJob);
}
function processScheduledJobs() {
running--;
if (semaphore && running < limit) {
semaphore.resolve();
semaphore = null;
}
}
return function () {
var args = arguments;
function runJob() {
return promiseFactory.apply(this, args);
}
return scheduleNextJob()
.then(runJob)
.finally(processScheduledJobs);
};
}
module.exports = {
limitConcurrency: limitConcurrency
}
我寫了一個小庫來做到這一點: https : //github.com/suprememoocow/qlimit
它非常易於使用,專門用於Q承諾:
var qlimit = require('qlimit');
var limit = qlimit(2); // 2 being the maximum concurrency
// Using the same example as above
return Q.all(items.map(limit(function(item, index, collection) {
return performOperationOnItem(item);
}));
它還可以用於限制特定資源的並發性,如下所示:
var qlimit = require('qlimit');
var limit = qlimit(2); // 2 being the maximum concurrency
var fetchSomethingFromEasilyOverwhelmedBackendServer = limit(function(id) {
// Emulating the backend service
return Q.delay(1000)
.thenResolve({ hello: 'world' });
});
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.