16

私は非同期呼び出しを作成する最も良い方法は、各呼び出しが以前の呼び出しが完了したかどうかに依存しているときに見つけようとしています。現時点では、以下に示すように定義されたプロセス関数を再帰的に呼び出すことによってメソッドを連鎖させています。javascriptで非同期呼び出しをチェーンする正しい方法は何ですか?

これは私が現在行っていることです。

var syncProduct = (function() { 
    var done, log; 
    var IN_CAT = 1, IN_TITLES = 2, IN_BINS = 3; 
    var state = IN_CAT; 
    var processNext = function(data) { 
     switch(state) { 
      case IN_CAT: 
       SVC.sendJsonRequest(url("/api/lineplan/categories"), processNext); 
       state = IN_TITLES; 
       break; 
      case IN_TITLES: 
       log((data ? data.length : "No") + " categories retrieved!"); 
       SVC.sendJsonRequest(url("/api/lineplan/titles"), processNext); 
       state = IN_BINS; 
       break; 
      case IN_BINS: 
       log((data ? data.length : "No") + " titles retrieved!"); 
       SVC.sendJsonRequest(url("/api/lineplan/bins"), processNext); 
       state = IN_MAJOR; 
       break; 
      default: 
       log((data ? data.length : "No") + " bins retrieved!"); 
       done(); 
       break; 
     } 
    } 
    return { 
     start: function(doneCB, logCB) { 
      done = doneCB; log = logCB; state = IN_CAT; 
      processNext(); 
     } 
    } 
})(); 

これが私のために完全に正常に動作している間、私は助けるが、よりよい(単純な)方法がなければならないと考えることはできません

var log = function(message) { 
    // Impl removed. 
} 

syncProduct.start(function() { 
    log("Product Sync Complete!"); 
}, log); 

を次のように私は、これを呼び出します。再帰呼び出しが深すぎると後で何が起こるのですか?

:私はブラウザでjavacriptを使用していませんが、ネイティブにTitaniumフレームワーク内で使用しています。これはNode.jsのJavascriptに似ています。

+1

「約束」を調べましたか?彼らは素敵に合うかもしれません。 [これはNode用に実装されたライブラリです(https://github.com/kriskowal/q)。 – pimvdb

+0

そのライブラリは素晴らしいpimvdbに見えますが、私はこれを使用していると思います。 –

答えて

26

そこライブラリとあなたのための非同期チェーンと制御フローを行うツールの多くがあり、彼らは主に二つの主要な種類があります:

  1. 制御フローライブラリ例えば

    は、 async,seqおよびstep(コールバックベース)またはQおよびfutures(約束ベース)を参照してください。これらの主な利点は、それらが非同期プログラミングの苦痛を和らげる平凡なJSライブラリであることです。

    私の個人的な経験によれば、約束のベースのライブラリは、「戻り値」を使用して値を返すため、実際の値と同様に約束値を渡して保存できるため、通常の同期コードに近いコードになりがちです。

    一方、継続ベースのコードは、明示的にコードパスを操作するため、より低レベルです。これにより、より柔軟な制御フローと既存のライブラリとのより良い統合が可能になるかもしれませんが、ボイラープラッタが多く、直感的ではないコードにつながる可能性もあります。

  2. JavascriptのCPSコンパイラあなたは非常に簡単な方法で非同期コードを書くことができますし、あなたがあればJavascriptを使用できることを意味言語の残りの部分との素敵な果たしているコルーチン/発電機用のネイティブサポートを追加するために、言語の拡張

    ステートメント、ループなどではなく、関数でそれらを複製する必要があります。これはまた、以前は同期コードを非同期バージョンに変換することが非常に簡単であることを意味します。しかし、すべてのブラウザがJavascript拡張機能を実行するわけではないので、継続的な渡しスタイルのコールバックを使用してコードを正規のJSに変換するために、ビルドプロセスにコンパイルステップを追加する必要があるという明らかな欠点があります。とにかく、Ecmascript 6仕様のジェネレータは有望な選択肢です.Firefoxだけがネイティブにサポートしていますが、regeneratorTraceurなどのプロジェクトがコールバックに戻してコンパイルします。独自の非同期構文を作成する他のプロジェクトもあります(es6ジェネレータはそれ以前には登場しませんでした)。このカテゴリでは、tamejsIced Coffeescriptなどが見つかります。最後に、Node.jsを使用する場合は、Fibersもご覧ください。


マイrecomendation:

あなたは自分のビルドproccessを複雑にしないだろう、単純な何かをしたい場合は、私は最高のあなたの個人的なスタイルに合うものは何でも制御フローのライブラリと一緒に行くお勧めしますと、あなたがすでに使っているライブラリ。

しかし、複雑で深く統合された非同期コードをたくさん書くことが予想される場合は、少なくともコンパイラベースの代替方法を検討することを強くお勧めします。

+0

優れたmissingnoは、私の質問へのコメントでpimvdbも言及した 'Q'ライブラリは完璧に見えます。私が道を行く前に、図書館のフィードバックをお願いできますか?私は最初の呼び出しで完全にブロックされている呼び出しですが、私は望んでいないと思います。 –

+2

@BrettRyan:実際には、私はDojoのツールキットのものを使用しています。そのため、約束のライブラリを使った経験が多く、代わりの経験はあまりありません。すべての異なるスタイルは、あなたが必要とするすべてのノンブロッキングなものを行うことができるはずなので、とにかくプログラミングスタイルをもっと見なければなりません。今すぐ何かを始める必要があるなら、私はCPSコンパイラの使用を重視しています。実際にどうなるかは分かりませんが、今はCPSコードを手作業で書いて何かを望んでいることに疲れていますより良い。 – hugomg

+0

ありがとうございます。私はAppcelerator Titanium Mobile SDKを使用していますので、実際には別のツールをツールチェーンに入れたくありません。 Qライブラリを試してみると、本当に自然にフィットするように見えます。 –

関連する問題