我怎样才能限制Q promise的并发性?

我如何编写一个限制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构造函数是在您的环境中进行填充或实现的),您可以这样做:

 //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的recursion是必要的,所以running < limitlimit++总是在同一个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 } 

延期承诺实现具有gatefunction,其function正是如此:

 spawnProcess = deferred.gate(spawnProcess, 5); 

我写了一个小库来做到这一点: https : //github.com/suprememoocow/qlimit

这是非常容易使用,是专门devise与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' }); });