簡體   English   中英

問 - 執行一系列承諾並在DAG中定義它們之間的依賴關系

[英]Q - executing a series of promises and defining dependencies between them in a DAG

我想處理一系列數據,其中每個數據的輸出可以用作其他數據的輸入。

例如:

    var batch = [
        {"id":"a1","depends":[],"data":{"some":"data a1"}},
        {"id":"b1","depends":["a1"],"data":{"some":"data b1"}},
        {"id":"b2","depends":["a1"],"data":{"some":"data b2"}},
        {"id":"c1","depends":["b1","b2"],"data":{"some":"data c1"}},
        {"id":"x1","depends":[],"data":{"some":"data x1"}},
    ];

這意味着一旦a1完成,其輸出將被發送到b1b2 ; 當這些完成時,它們的兩個輸出都將被發送到c1 (僅在它們完成時兩個x1可以與所有a1b1b2c1並行執行;並且b1可以與b2並行執行,因為no depends它們之間的定義。

完成c1x1 ,並因此完成所有5個后,應返回所有五個的輸出。

我們假設沒有定義循環依賴,因此是有向無環圖(DAG)

我想知道如何使用Q實現這個,因為:

  • 所有數據處理都是異步的,因此我需要使用回調,延遲和承諾; 而我更喜歡后者
  • Promise可以加倍作為定義圖中邊緣的便捷方式

但是,我未能將這個過去概念階段

var doPromises = {};

var doData = function(data, dependsResultsHash, callback) {
  //Not real processing, simply echoes input after a delay for async simulation purposes
  var out = {
    echo: {
      data: data,
      dependsResultsHash: dependsResultsHash
    }
  };
  setTimeout(function() {
    callback(out);
  }, 1000);
};

var doLine = function(id, depIds, data) {
  var deferred = Q.defer;
  var dependsPromises = [];
  for (var i = 0; i < depIds.length; ++i) {
    var depId = depIds[i];
    dependPromise = doPromises[depId];
    dependsPromises.push(dependPromise);
  }
  Q.all(dependsPromises).then(function(dependsResults) {
    var dependsResultsHash = {};
    for (var i = 0; i < depIds.length; ++i) {
      var depId = depIds[i];
      var depResult = dependsResults[i];
      dependsResultsHash[depId] = depResult;
    }
    doData(data, dependsResultsHash, function(result) {
      deferred.resolve(result);
    });
  });
  return deferred.promise;
}

var doBatch = function(batch) {
  var linePromises = [];
  for (var i = 0; i < batch.length; ++i) {
    var line = batch[i];
    var linePromise = doLine(line.id, line.depends, line.data);
    linePromises.push(linePromise);
    doPromises[line.id] = linePromise;
  }
  Q.all(linePromises).then(function(lineResults) {
    console.log(lineResults);
    deferred.resolve(lineResults);
  });
};

doBatch(batch);

(請注意,此代碼未經測試,我認為它不起作用,只是為了說明我的問題所必需的點。)

我想知道:

  • 我這樣做了嗎? 我是否完全忽略了Q庫的重點。 還是延期和承諾?
  • 我主要關心的是doData函數:

     -- Is the way that I have selected the promises of the lines depended upon from the global list of promises `doPromises` ok? -- Is the way that I have obtained the results of the lines depended upon, and inpterpreted that OK? 
  • 使用doBatch函數:

     -- I have a local array for `linePromises` and an external hash for `doPromises`, and I feel that these should be combined. How can I do this correctly? 
  • 一般

     -- The code above presently assumes that all `deferred`s will eventually keep their `promise`s. What if they fail or throw an exception; how do I make my code more robust in handling this? -- I have used a closure allow acces to `doPromises` in both `doBatch` and `doLine`, and it seems a little odd here, is there a better way to do this? 

我創建了一個執行此操作的庫:

qryq是一個NodeJs庫,它允許表達一系列查詢並在它們之間並行,按順序或在有向非循環圖中定義它們之間的依賴關系。

我最近創建了一個名為dagmise的模塊,我計划用它來構建一個使用promises作為任務的構建系統。 我最終制作了返回promises的圖形函數的節點。 訪問節點時,將評估其中的函數,並且返回的promised將其作為節點的值。 因此,即使多次訪問節點,該函數也只執行一次。

我開始認為承諾應該是邊緣,但現在我認為將它們放在節點上更簡單。 否則你最終會在圖形中出現兩種對象(節點/狀態和邊緣/承諾),這會使事情變得復雜。

我剛剛為此實現了自己的庫: promise-dag

由於以下原因,我對提到的替代品( dagmiseqryq )不滿意:

  • 他們強制實施Promise。 promise-dag與任何Promise實現兼容,沒有任何代碼依賴。
  • 它們提供了流暢的API(鏈接方法)。 我更喜歡面向數據的API,它更具可編程性和透明性,可以很容易地使用普通的數據結構函數( _.extend()_.pick() ,...)組合計算圖,以及添加自定義檢測(分析/跟蹤/記錄/等)。

暫無
暫無

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

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