2011-07-29 7 views
3

コールバックを持つ他の(潜在的に非同期の)関数の不確定な数を呼び出す必要がある関数を持つ関数を持つ私は次のパターンを使用しています。javascriptでは、コールバックで複数の非同期関数を実行するためのベストプラクティスは何ですか?

確かにそれは正しいですが、審美的にはあまり喜ばれません。私に

 
// fn responsible for figuring out and calling aysnc funcs 
function fn(arg, outNext) { 

     // calculate how many funcs we will be calling 
     var waitCt = 0; 
     var a, b, c; 
     if(a = arg['a']) waitCt++; 
     if(b = arg['b']) waitCt++; 
     if(c = arg['c']) waitCt++; 

     // call funcs 
     if(a) fnArbitrary(arg.a, inNext); 
     if(b) fnRandom(arg, inNext); 
     if(c) fnClueless(15, inNext); 

     // calback func 
     function inNext(err) { 

       // wait for one less func 
       waitCt--; 

       // return err if found 
       if(err) outNext(err); 

       // return nada if all funcs performed 
       if(waitCt == 0) outNext(); 

       // otherwise we're waiting for other funcs to finish 
       return; 
     } 
} 

2つのステップを取る必要があると思わ:呼び出されますどのように多くのfuncs見て最初に、呼び出しを行うための第二。しかし、たぶん私の脳は、昔の学校のプログラミングか、昨夜のリアのレ

+0

fa、fb、およびfcをどこで定義したか不明です。あなたの関数にサンプル呼び出しを投稿してください。 – mamoo

+0

@mamoo - fa、fb、およびfcは、コールバックを持つ任意の関数です(たとえば、データベースへのポスティングまたはデータベースからの読み取りなど)。 (実際のコードは非常に大きく、絡み合っています) –

答えて

3

のようなフロー制御のいくつかのフォームを使用するためにin this Script Junkie articlethis article about the FutureJS implementationthis msdn articleこのStack Overflow questionを説明するように、私は複数のaysnc機能のために見た中で最高の経営理念は、Deferredの作り方や先物です。

実際には、複数の非同期呼び出しを順序付けしたり、それらの間の実行依存関係を定義する構造化された方法であり、異なるフレームワークで進行中の複数の実装(既に使用可能)で牽引力があるようです。今と将来の両方を学ぶのに役立ちます。

それらの間の依存関係を持つ複数の非同期呼び出しを手作業で管理することは実際には面倒です。コードが乱雑に見えるだけでなく、読み込みが不可能で、デバッガを使用することも不可能です。デバッグには通常、たくさんの情報をログファイルにダンプしてから、何が起きたかを整理する必要があります。タイミングが関係する場合は、あなたは本当に混乱のためです。私の最後のプロジェクトでは、未解決のバグがまだ残っている唯一の領域は、起動時の4つの異なる非同期呼び出しの間の何らかの依存関係の欠落です。私はエラーをほとんど起こらないようにコードを強化しましたが、それはまだあまり行っていません。次のステップは、deferredsの使用に切り替えて、それに正式な構造を追加することです。大きなライブラリの一部については

、我々はYUI3は(一般のDeferred未満強力であるが、有益な)Async Queueを持って、道場はDeferred objectを持ち、に縛られていないカップル繰延ライブラリが存在し、jQuery Defereds持っていますメインライブラリ。

+0

はnode.jsからの約束を知っていますが、普遍的な実装から非常に遠いと思っていました –

+0

「普遍的に実装された」とは現在の状況にはあまりにも強すぎますが、そのコンセプトには牽引力があるようです使用する実装があります。私は個人的には、より多くの牽引力できれいに動作する他のものを見たことはありません。 – jfriend00

+0

あなたが参照したメインライブラリはmsdnのものです。これはあなたが使っているものですか? (私の(イホの正当化された)msから発信されたコードの不信を許してください。) –

1

私はユーティリティ機能を持っています。

var after = function _after(count, f) { 
    var c = 0, results = []; 
    return function _callback() { 
    switch (arguments.length) { 
     case 0: results.push(null); break; 
     case 1: results.push(arguments[0]); break; 
     default: results.push(Array.prototype.slice.call(arguments)); break; 
    } 
    if (++c === count) { 
     f.apply(this, results); 
    } 
    }; 
}; 

// fn responsible for figuring out and calling aysnc funcs 
function fn(arg, outNext) { 

    var cb = after(Object.keys(arg).length, function(data) { 
     // all finished. Do something 
    }); 

    // replace fa, fb, fc with f['a'], f['b'], f['c'] 
    Object.keys(arg).forEach(function(k) { f[k](arg[k], cb); }); 
} 

これは、単純なケースで使用します。より複雑な状況がFutures

+0

これはどのように動作するかはわかりません。 'after()'の呼び出しでは '3 'が固定されていますが、実際に呼び出される関数の数は' after() 'に渡す必要があります。 - または何かが欠けている? –

+0

@cc_youngバグだった。 'Object.keys(arg).length'を渡すことは、存在する引数の量に対してのみ行います。 – Raynos

関連する問題