5

それぞれの出力を他のデータへの入力として使用できる一連のデータを処理したいと思います。

例えば:

    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送信されることを意味します。これらが完了すると、両方の出力が に送信されます(両方が完了した場合のみ。 、、、およびのすべてと並行して実行される場合があります。また、 と並行して実行される場合があります。これらの間には定義されていないためです。b1b2c1x1a1b1b2c1b1b2depends

と が完了するc1x1、したがって 5 つすべてが完了すると、5 つすべての出力が返されます。

循環依存関係が定義されていないため、有向非巡回グラフ (DAG) であると仮定します。

Qを使用してこれを実装する方法を知りたいのですが、理由は次のとおりです。

  • データの処理はすべて非同期であるため、コールバック、または deferred と promise のいずれかを使用する必要があります。そして私は後者を好みます
  • 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?
    
4

3 に答える 3

1

このために独自のライブラリを実装しました: promise-dag

次の理由により、上記の代替案 ( dagmise、 ) に満足できませんでした。qryq

  • それらは、具体的な Promise の実装を課します。promise-dagコードに依存することなく、あらゆる Promise 実装と互換性があります。
  • それらは流暢な API (連鎖メソッド) を提供します。私は、よりプログラム可能で透過的なデータ指向 API を好みます。これにより、通常のデータ構造関数 ( _.extend()_.pick()、...) を使用して計算グラフを簡単に結合したり、カスタム インストルメンテーション (プロファイリング / トレース / ロギング / など) を追加したりできます。 .)。
于 2016-12-06T15:11:54.543 に答える
1

これを行うライブラリを作成しました:

qryqは、一連のクエリを表現し、それらの間の依存関係を並列、順番、または有向非巡回グラフで定義できるようにする NodeJs ライブラリです。

于 2014-02-26T00:05:43.730 に答える