2016-04-11 11 views
2

JavaScriptプロミスに問題があります。依存関係を減らすためにネイティブ実装を使用しています。promise.allのネストされたpromise.allを待つ方法

私が必要とするものの具体的な例。

書籍のリスト、著者と購入者を検索する必要があります。 私は、各著者の著者プロフィールも必要です。私はそのすべてを手に入れた後、本と書籍の購入リストを使って素敵なセットの作家を作成する必要があります。

リストとプロファイルは別々のAPI JSON呼び出しです。唯一の依存関係は、著者プロファイルを取得するために著者のリストが必要なことです。

私はこれを約束で解決しました。 Promise.allを使用して、著者、書籍、購入の3つのAPI JSONリクエストを取得します。 私はもう一つのPromise.allを使用して、私が得た各著者のすべてのプロファイルを取得します(リストをループし、各プロファイルのURLをマップし、並行して要求のバッチを送信します)。

私は著者のリストを取得するとすぐにプロファイル要求バッチを実行します。したがって、著者リストの約束の "Then"ハンドラで実行します。

さて、問題:

すべての約束、3つのリスト、すべてのプロファイルは、以前のライブラリのセットの私の組み立てに行われることを確認するために、私はリクエストのプロフィールバッチを送信する必要があります私がすべてのリストで完了したら、最初のPromise.all Thenハンドラで。

しかし、書籍のリストは、著者のリストよりもはるかに長い時間がかかり、すべての人がプロファイル要求のバッチを送るのを待っていないので、私はそれを私は情報を持っているとすぐにこれらの開始ので、著者リスト約束。

しかし、ネストされたPromise.allは親Promise.allにカウントされません。したがって、FinalFunctionがトップレベルのPromise.allのThenにあるため、ネストされる前に起動されることがありますPromise.allはすべての著者プロファイルの検索を終了しました。

すべてのPromiseリクエストをできるだけ早く開始できるようにする必要がありますが、作成者のリクエストのバッチのみが1つの約束が開始することに依存しているため、そのリクエストを待つ必要があります。その他はすべて独立して開始する必要があります。

擬似コード

Promise.all(
    requestBooks().then(){}, 
    requestAuthors().then(){ 
    GenerateArrayOfAuthorUris(); 
    // now send a promisifyed batch of per-author requests 
    Promise.all(
     [array of author uris to run requests for] 
    ) 
    .then(){ 
     // If I run this here, I may not have upper-level requests done 
     runCalculationsPerAuthorForAllAuthorsBooksPurchasesReceived(); 
    } 
    }, 
    requestPurchases().then(){}, 
) 
.then(){ 
    // this will fire when 3 top requests are done, but won't wait for 
    // the nested Promise.all with per-author requests 
    runCalculationsPerAuthorForAllAuthorsBooksPurchasesReceived(); 
} 

私はこのようにそれを行う場合、私はちょうどごとの著者の要求を開始するために待つ必要はありませんリクエストを待つことによって、貴重な時間を無駄にしています:

Promise.all(
    requestBooks().then(){}, 
    requestAuthors().then(){ 
    GenerateArrayOfAuthorUris(); 
    }, 
    requestPurchases().then(){}, 
) 
.then(){ 
    // now send a promisifyed batch of per-author requests 
    Promise.all(
     [array of author uris to run requests for] 
    ) 
    .then(){ 
     // If I run this here, I may not have upper-level requests done 
     runCalculationsPerAuthorForAllAuthorsBooksPurchasesReceived(); 
    } 
} 

これは私が必要としていることを明確にします。

ありがとうございます。

これは、コードサンプルです:あなたがコメントで言われたとおりhttps://jsbin.com/qizohasofa/edit?js,console

+0

。あなたのコードでフィドルを作成できますか(それらの要求をいくつかのタイムアウトで置き換えてください)? – llamerr

+0

更新されたバージョンがあります。 – Anthony

+0

あなたは 'Promise.all'パラメータの周りに配列リテラルを作るのを忘れてしまい、非同期なことを行う' then'コールバックから 'return'を約束するのを忘れたようです。擬似コードの代わりに実際のコードを表示すると役立ちます。 – Bergi

答えて

1

、あなたはあなたの関数からreturn何でもそうthenは、内側の約束を待つために何を知らなかった、しませんでした。テキストの多くはだと私は(まだ)それを読んでいないが、あなたは `欠けているように、どこかyourPromiseVar`を返すか何かのようなタイトルから、それが聞こえる

function getJokeCategories() { 
    return Promise.all([ 
// ^^^^^^ 
     pgetJSON("http://api.icndb.com/categories"), 
     pgetJSON("http://api.icndb.com/jokes/count").then(function(data) { 
      var jokesToGet = []; 
      for (var i=0; i<data; i++){ 
       jokesToGet.push("http://api.icndb.com/jokes/"+i); 
      } 
      return Promise.all(jokesToGet.map(function(jk) { 
//   ^^^^^^ 
       return pgetJSON(jk).then(function(joke) { 
//    ^^^^^^ 
        console.log(jk + " just returned", joke); 
        return joke; 
//     ^^^^^^ 
       }); 
      })).then(function(jokes) { 
       console.log("All jokes returned. This does happen only when all jokes are retrieved."); 
       return {count:data, jokes:jokes}; 
//    ^^^^^^ 
      }); 
     }) 
    ]); 
} 
getJokeCategories().then(function(result) { 
    console.log(result, "This does happen at the very end when joke count, joke categories and all jokes are returned."); 
}); 
+0

私は今、コメントを見て理解しています。 Promise.allsとその中の約束の両方から戻り、それを機能させる必要がありました。すべてよりも少ないものはただ失敗しました。 – Anthony