簡體   English   中英

如何限制Q promise並發?

[英]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 < 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
}

延遲承諾實現具有gate函數,其功能完全相同:

spawnProcess = deferred.gate(spawnProcess, 5);    

我寫了一個小庫來做到這一點: 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM