簡體   English   中英

Q promises中的並發限制 - 節點

[英]Concurrency limit in Q promises - node

有沒有任何方法可以使用Q promises庫限制promises的並發性?

這個問題與我如何限制Q promise並發有關?

但問題是我正在嘗試做這樣的事情:

for (var i = 0; i <= 1000; i++) {
  return Q.all([ task1(i), task2(i) ]); // <-- limit this to 2 at a time.
}

真實的用例是:

  1. 從DB中獲取帖子
  2. 循環DB中的每個帖子,如posts.forEach(function(post) {}
  3. 對於每個帖子做task1,task2,task3(檢索社交計數器,檢索評論計數等)
  4. 在DB中保存新的帖子數據。

但問題是節點同時執行所有帖子的所有任務,比如同時向facebook詢問500個帖子的“喜歡計數”。

我如何限制Q.all()所以一次只有2個帖子正在執行他們的任務? 或者其他可能的解決方案適用於此?

注意:大多數任務(如果不是全部)都依賴於請求庫

感謝Dan,他的回答以及將其與我的代碼集成的幫助,可以使用他的要點和這樣的snipplet來完成:

var qlimit = require('../libs/qlimit');

var test = function(id) {
  console.log('Running ' + id);
  return Q.nfcall(request, 'some dummy url which takes some time to process, for example a php file with sleep(5)').spread(function(response, body) {
    console.log('Response ' + id);
    return body;
  });
}

test = qlimit.limitConcurrency(test, 1);

var data = [0, 1, 2];

data.forEach(function(id) {
  console.log('Starting item ' + id);
  Q.all([ test(id) ]);
});

這樣你會得到類似的東西:

  • 從第0項開始
  • 從第1項開始
  • 從第2項開始
  • 運行0
  • 回復0
  • 跑步1
  • 回應1
  • 跑2
  • 回應2

這顯然是一次1個請求。

我在實現中缺少的重點是你需要在啟動循環之前使用limitConcurrency重新聲明函數,而不是在它內部。

幾天前我問了一個非常類似的問題: Node.js / Express和並行隊列

我找到的解決方案(參見我自己的答案)是使用Caolan的異步 它允許您創建“操作隊列”,並且您可以限制可以並發運行的數量:請參閱“隊列”方法。

在您的情況下,Node的主循環將從Q中提取元素,並在隊列中為每個元素創建一個任務。 你也可以限制它(所以不要基本上重新創建Q之外的隊列),例如,只有在最后一個元素被執行時才向隊列添加N個新元素(“隊列”方法的“空”回調) )。

是我用來限制q承諾的代碼。

我剛把它從我需要它的項目中刪除了。 如果有更多人感興趣,我可以將其分成一個模塊或其他東西。

查看方法spex.pagespex.sequence 它們旨在實現任何可能的數據限制策略+承諾的負載平衡

請參閱以下項目文檔中的幾個示例。

平衡頁面來源

以下示例使用方法頁面啟動5個頁面的序列,然后將已解析的數據記錄到控制台中。 源函數為每個頁面提供半秒延遲。

var $q = require('q');    
var spex = require('spex')($q);

function source(index, data, delay) {
    return new $q.Promise(function (resolve, reject) {
        setTimeout(function () {
            resolve([
                "page-" + index, // simple value;
                $q.resolve(Date.now()) // promise value;
            ])
        }, 500); // wait 1/2 second before serving the next page;
    });
}

function logger(index, data, delay) {
    console.log("LOG:", data);
}

spex.page(source, {dest: logger, limit: 5})
    .then(function (data) {
        console.log("FINISHED:", data);
    });

輸出:

LOG: [ 'page-0', 1446050705823 ]
LOG: [ 'page-1', 1446050706327 ]
LOG: [ 'page-2', 1446050706834 ]
LOG: [ 'page-3', 1446050707334 ]
LOG: [ 'page-4', 1446050707839 ]
FINISHED: { pages: 5, total: 10, duration: 2520 }

平衡序列接收器

在下面的示例中,我們有一個在索引小於5時返回數據的序列 ,以及在處理從源解析的每個數據時強制執行1秒延遲的目標函數。

var $q = require('q');    
var spex = require('spex')($q);

function source(index, data, delay) {
    console.log("SOURCE:", index, data, delay);
    if (index < 5) {
        return $q.resolve(index);
    }
}

function dest(index, data, delay) {
    console.log("DEST:", index, data, delay);
    return new $q.Promise(function (resolve, reject) {
        setTimeout(function () {
            resolve();
        }, 1000);
    });
}

spex.sequence(source, dest)
    .then(function (data) {
        console.log("DATA:", data);
    });

輸出:

SOURCE: 0 undefined undefined
DEST: 0 0 undefined
SOURCE: 1 0 1011
DEST: 1 1 1001
SOURCE: 2 1 1001
DEST: 2 2 1001
SOURCE: 3 2 1000
DEST: 3 3 1000
SOURCE: 4 3 1001
DEST: 4 4 1001
SOURCE: 5 4 1000
DATA: { total: 5, duration: 5013 }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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