すべての非同期呼び出しの後

そのため、非同期リクエストを大量に含むアプリケーションを作成しています。 2つの非同期リクエストを送信し、両方の結果が受信された後にのみ結果を処理する必要があります。 たとえば、非同期ファイルアクセスとデータベースへの要求があり、その結果を一緒に追加して処理する必要があります。 または、2つのajaxリクエスト。

しかし、非同期リクエストの特徴は、どれが最初に来て最後に来るかわからないことです。 彼らはさまざまな方法でこれを解決しますが、私はまだ美しくエレガントなものを見ていません。 トピックでは、私がそれをどのように見るかを説明します。

var process = processFsAndDb.after('fs', 'db'); asyncFsAccess( file, process.fs); asyncDbAccess(query, process.db);
      
      







通常、次のいずれかを実行します。



たぶんラッキー



通常、これを実行できるのは非同期呼び出しを理解していない人だけです。 このようなもの:

 var fileData = null; asyncFsAccess( file, function (data) { fileData = data; }); asyncDbAccess(query, function (dbData) { processFsAndDb(fileData, dbData); });
      
      





ファイルシステムの処理が少し遅くなり、データベースからのリクエストが速くなったと想像してください。 この場合、fileDataには何もありませんが、このデータは単純に分解しませんでした! 悲しい...



彼とイチジク、私は待ちます



別のオプションは、少なくとも信頼性があります。 1つのリクエストを作成し、完了するまで待ち、2番目のリクエストを作成します。

 asyncFsAccess( file, function (fileData) { asyncDbAccess(query, function (dbData) { processFsAndDb(fileData, dbData); }); });
      
      





これは最善の望みよりはましですが、ここでは時間を犠牲にしています。ファイルシステムへのアクセス中にデータベースが既に検索されている可能性がありますが、そうではありません。 そして、ajaxの場合、ユーザーは2倍の長さの回答を待ちます。 良くない



7回チェック



システムまたは変数のチェックにフラグを立てます。 各リクエストの後に、それに対応するフラグをマークし、すべてのフラグがチェックされた場合、それを実行します。 最も正しいオプション。

 var fileData = dbData = null; asyncFsAccess( file, function (data) { fileData = data; if (fileData && dbData) processFsAndDb(fileData, dbData); }); asyncDbAccess(query, function (data) { dbData = data; if (fileData && dbData) processFsAndDb(fileData, dbData); });
      
      





しかし、あまり美しくありません。 コードが繰り返され、フラグは多くの場所に追加する必要があります。 3つの同時リクエストを送信する必要がある場合-dofigaテキストがあります



7回チェック++



 var fileData = dbData = null; var process = function () { if (fileData && dbData) processFsAndDb(fileData, dbData); }; asyncFsAccess( file, function (data) { fileData = data; process(); }); asyncDbAccess(query, function (data) { dbData = data; process(); });
      
      





良いですが、あまり良くありません。 フラグは4回繰り返されます(fileData変数の数をカウントします)



私のオプション、プロトタイプを展開



結果として、コードは次のとおりです。

 var process = function (args) { processFsAndDb(args.fs, args.db); }.after('fs', 'db'); asyncFsAccess( file, process['fs']); asyncDbAccess(query, process['db']);
      
      







または、これでも:

 var process = processFsAndDb.after('fs', 'db'); asyncFsAccess( file, process.fs); asyncDbAccess(query, process.db);
      
      







実際、フラグ付きのオプションを使用しますが、メソッドの下に抽象化し、関数プロトタイプに追加します。

 Function.prototype.after = function () { /** * @var onReady -   -,        * @var after -   ,    . *        (process.fs  process.db) * @var ready -           , *    after    - ,   onReady */ var onReady = this, after = {}, ready = {}; var checkReady = function () { for (var i in after) if (!(i in ready)) return; onReady(ready); }; for (var i = 0, l = arguments.length; i < l; i++) { (function (key) { after[key] = function () { ready[key] = arguments; checkReady(); }; })(arguments[i]); } return after; };
      
      







これは非常に便利で美しい方法で、このようなまれではあるが重要な作業だと思います。



All Articles