2013-03-19 31 views
8

JavaScriptで非同期コードを扱う際に、どちらの方が良いか知りたい。どのメソッドがよりクリーンなコードになるのか理解したい。私は約束に使用されており、非同期アプローチ(https://github.com/caolan/async)よりも柔軟性があるようです。task.jsジェネレータ/約束と非同期のコールバック

私はTask.jsライブラリ(http://taskjs.org/)についても知っていますが、これはEcmascript Harmonyの一部であるyieldキーワードに依存しています。

+2

リンクされた非同期ライブラリを使用する主な利点は、非同期スタイルの多くの一般的な操作をラップまたは提供することです。 "plain" [Promises](http://wiki.commonjs.org/wiki/Promises/A)(つまりjQuery.Deferred)を使用することができますが、より多くの定型句が必要になります。非同期スタイル)を使用して、上記の関数の独自のバージョンを書く必要があります。リンクされた非同期ライブラリと約束は最終的に同じ方法で動作します。*コールバック*が使用されます。 –

+3

私が約束していることは、関数から何かを返す代わりに、後で呼び出すコールバックを受け入れるということです(この瞬間にこの値を返すことはできませんが、値を取得します)。私が気に入らないのは、2つの関数を渡さなければならないということですが、これはEcmaScript Harmonyの準備が整うと解決されます。 Task.jsがとても素晴らしいという事実を考えれば、約束は本当に将来の証明です。おそらく、約束事とコールバックの間のギャップ(非同期のようなものですが、約束を返す)を閉じるモジュールを開発することは興味深いでしょう。 –

答えて

3

あなたの質問にnodeというタグが付いているので、私は非同期ライブラリをお勧めします。コントロール・フロー関数は、コールバック・チェーンに従うのが面倒で難しい作業をして排除するのに最適です。 APIは、ノードのシグニチャ(error, result)に続くコールバックを制御関数に注入するために本当にいい設定です。基本的には、私が書いたほぼすべてのノードスクリプトにデフォルトで含まれています。

クライアント側でもasyncを使用できますが、ほとんどのプロジェクトではおそらく不要です。 jQueryには約束が含まれており、それらを使って同じことを達成できます。

1

私は約束の焦点を1つのステップの非同期操作の進行に約束し、非同期のフォーカスを多段の非同期操作でノードに対して非同期のapiの多くのための広い使用を持っています。道による

、非同期操作に対処するには、代わりに無名関数を使用するという名前の関数は asyncライブラリが並行して、任意の非同期呼び出しを行うなど、非常に一般的な非同期パターンのカップルを、カプセル化する最も効果的な方法

11

になります非同期的にリストを反復処理します。これは、 "nodeback" (err, res) APIで動作するように設計されているため、多くのNode.jsアプリケーションにとって便利です。しかしasync特有のソリューションであり、ライブラリに含まれる非同期パターンを単純化するだけです。対照的に、約束は、私の意見では、はるかに多くです。一般非同期コードの問題の解決策です。エラーバブリングとコールバックピラミッドの平坦化の明らかな利点を提供するだけでなく、複雑なパターンの複雑なパターンを必要とする問題は、より簡単に解決することができます。

asyncの利用可能なパターンの一部を使って簡単に説明します。たとえば、async.waterfall関数は次のようなものに使用されます。

async.waterfall([ 
     function (cb) { 
     asyncCall('argument', cb); 
     }, 
     function(resultOfFirstCall, cb) { 
     anotherCall(resultOfFirstCall, 'someOtherArgument' cb); 
     }, 
    ], function(err, res) { 
     if (err) handle(err); 
     useFinalResult(res); 
    }); 

async.waterfallに相当するものがほとんどでありません、それはそれを実装するためにとてもシンプルだから、(または少なくともQの1が存在しない)のライブラリを約束そのように、Array.reduceを使用してゼロから(例えば、他の約束ライブラリに同じかなりのQに基づいていますが):async

[ 
    function() { 
    return asyncCall('argument'); 
    }, 
    function(resultOfFirstCall) { 
    return anotherCall(resultOfFirstCall, 'someOtherArgument'); 
    } 
].reduce(Q.when, Q()) 
.then(useFinalResult, handle); 

他の大きな機能は、QがQ.allとして含まasync.parallelを、次のとおりです。

// async 
async.parallel([ 
    asyncFunc, 
    asyncFunc2 
    ], function(err, res) { 
     if (err) handle(err); 
     useFinalResult(res); 
     // res[0] === asyncFuncResult 
     // res[1] === asyncFunc2Result 
    }); 
// Q 
Q.all([ 
    asyncFunc(), 
    asyncFunc2() 
]).then(useFinalResult, handle); 

およびasync.map

// async 
async.map(['file', 'file2', 'file3'], fs.stat, function(err, res) { 
    if (err) handle(err); 
    useFinalResult(res); 
}); 
// Q 
Q.all(['file', 'file2', 'file3'] 
    .map(Q.nfbind(fs.stat))) 
    .then(useFinalResult, handle); 

asyncの残りの部分はあなたの約束ライブラリの比較的単純な片を用い、簡潔に実装するのも同様に簡単です:あなたは約束を使用しているとき、通常のArray.mapが十分にあるので、あなたが実際にasync.mapを必要としません。 (最後の例は関数Q.nfbindnfbindを使用し、他のnf*関数Qは基本的にnodeback APIで約束したものを使用する必要があるので、ノードバックを期待するライブラリで約束を使用しようとすると、あなたが約束またはnodebacksを使用するかどうかを最終的には。)

は、あなた次第ですが、私は約束は、ほとんどすべての非同期動作を実行するためのより柔軟、能力、および一般的に簡潔な方法だと思います。

Callbacks are imperative, promises are functionalは、この一般的な内容の詳細について読む価値があります。

0

gumballheadは async.js をお勧めしますが、は、あなたがノードで作業している場合Parse Cloud Codeを使用することをお勧めします。彼らのAPIは、他の特典(データベースのようなもの)とともに、すぐに構築された約束を持っています。それは時間を節約し、バックエンドの安定性を心配する必要はありません。 module.exportsのちょっとした調整をしたのNPMモジュールを含めることができます。また、フロントエンドとシームレスに統合されます。私は現在のプロジェクトでこのアプローチを成功させており、新しいアプローチでコメントしたいと思っています。

何か理由がある場合はいつでもコメントしてください/ クラウドコードを使用してください。私はまだそのような経験はなかったからです。