17

async と Q 全般

私は Node.js 開発を学んでおり、非同期の「コールバック地獄」を管理するための戦略に頭を悩ませようとしています。私が調査した 2 つの主な戦略は、Caolan McMahon のasyncモジュールと、Kris Kowal の promise ベースのQモジュールです。

の多くの人と同じように、私はまだどちらを使うべきかを理解するのに苦労しています。しかし、一般的に言えば、Promise と Q ベースのコードの方がやや直感的であることがわかったので、その方向に進んでいます。

一般的なコレクションのマッピング/連結

ただし、コレクションを管理するための async モジュールの関数の使用にはまだ行き詰まっています。Java と Python のバックグラウンドを持っているため、コレクションを扱うときのほとんどの場合、ロジックは次のようになります。

  1. 結果を格納する新しい空のコレクションを初期化します。
  2. 古いコレクションで for-each ループを実行し、各要素にロジックを適用して、その結果を新しい空のコレクションにプッシュします。
  3. for-each ループが終了したら、新しいコレクションの使用に進みます。

クライアント側の JavaScript では、jQuery のmap() 関数を使用することに慣れてきました...そのステップ 2 のロジックを渡し、ステップ 3 の結果を戻り値として取得します。基本的な考え方は同じような気がします。

async と Q を使用したコレクションのマッピング/連結

Node-side async モジュールには同様のmap関数とconcat関数がありますが、元のスコープ レベルで連結された結果を返すことはありません。結果を使用するには、代わりにコールバック地獄に降りる必要があります。例:

var deferred = Q.defer();

...

var entries = [???]; // some array of objects with "id" attributes

async.concat(entries, function (entry, callback) {
    callback(null, entry.id);
}, function (err, ids) {
    // We now have the "ids" array, holding the "id" attributes of all items in the "entries" array.
    ...
    // Optionaly, perhaps do some sorting or other post-processing on "ids".
    ...
    deferred.resolve(ids);
});

...

return deferred.promise;

then()私の他の関数は promise ベースになっているため、チェーン に簡単に含めることができるように、promise オブジェクトを返すこのコードを用意しています。

本当に両方必要ですか?

明確にするのに苦労している究極の質問は、上記のコード例でasyncQ の両方が本当に必要かということです。一般的に、非同期モジュールの制御フローをQスタイルのプロミスチェーンに置き換える方法を学んでいます...しかし、プロミスベースのアプローチでコレクションのマッピングまたは連結を行う方法はまだ「クリック」されていません。または、なぜできないのか、またはなぜそれが良くないのかを知りたいです。

上記の例で使用しているように、async と Q が連携して動作することを意図している場合は、それで問題ありません。しかし、Q を単独できれいに使用できるのであれば、追加のライブラリ依存関係を必要としないことを好みます。

(とんでもなく明白な何かを見逃していたらすみません。非同期イベント駆動型モデルは非常に異なる世界であり、私の頭はまだ泳いでいます。 )

4

1 に答える 1

27

本当に両方必要ですか?

いいえ。コレクションに対する非同期反復子のマッピングは、Promise を使用すると非常に簡単ですが、1 つの関数呼び出しではなく 2 つの手順が必要です。最初に、並列反復のためにコレクションがmappromiseの配列に渡されます。次に、これらの promise をフィードしQ.allて、マップされたコレクションの 1 つの promise を作成します。とは対照的にasync、結果の順序は保証されます。

var entries = […]; // some array of objects with "id" attributes

var promises = entries.map(function(object) {
    return asyncPromiseReturingFunction(object);
}); // the anonymous wrapper might be omitted
return Q.all(promises);

の場合concat、追加する必要があります

.then(function(results) {
     return Array.prototype.concat.apply([], results);
});
于 2013-08-02T13:45:19.347 に答える