17

Webサイトから一連のデータをフェッチする必要がある単純なWindows8アプリに取り組んでいます。WinJS.xhr()を使用してこのデータを取得し、Promiseを返します。次に、このPromiseの.then()メソッドにコールバックを渡します。これにより、非同期呼び出しからの戻り値がコールバックに提供されます。.then()メソッドは別のPromiseを返し、コールバックが返す値を返します。このようなクエリの基本構造は次のようになります。

WinJS.xhr({ url: "http://www.example.com/" }).then(
    function callback( result_from_xhr )
    {
        //do stuff
        return some_value;
    }).then(
    function secondcallback( some_value )
    {
        //do stuff
    });

ただし、私の状況では、最初のクエリによって返されたデータに応じてデータに対して追加のクエリを実行する必要があり、そのデータに応じてさらに多くのクエリを実行する必要がある場合があります...など。

次のように、すべての再帰が完了するまでfinal .then()が実行されないようにこれをコーディングする方法が必要です。

function recurse() {
    return WinJS.xhr({ url: "http://www.example.com/" }).then(
        function callback( result_from_xhr )
        {
            if( result_from_xhr == something )
            {
               recurse();
            }
        });
}

recurse().then(
function final()
{
    //finishing code
});

問題は、もちろん、最初のレベルの再帰が完了するとすぐに終了コードが呼び出されることです。コールバック内から新しいpromiseと古いpromiseをネストする方法が必要です。

私の質問が十分に明確であることを願っています。それを説明する方法が本当にわかりません。率直に言って、非同期再帰コードのアイデアは頭を痛めます。

4

4 に答える 4

14

ここで行うことは、手動で完了することができるまったく新しいスタンドアロンのPromiseを作成し、それをrecurse()関数から返すことです。次に、非同期作業が完了したことがわかったら、その約束を完了します。

Promise.joinは、既知の一連のPromiseがある場合に機能します。joinを呼び出す前に、利用可能なPromiseの配列全体が必要です。私が元の質問に従った場合、あなたはさまざまな数の約束を持っており、非同期作業の一部としてポップアップする可能性が高くなります。このような状況では、参加は適切​​なツールではありません。

それで、これはどのように見えますか?このようなもの:

function doSomethingAsync() {
  return new WinJS.Promise(function (resolve, reject) {
    function recurse() {
      WinJS.xhr({ url: "http://www.example.com/" })
        .then(function onResult(result_from_xhr) {
          if (result_from_xhr === something) {
            recurse();
          } else {
            // Done with processing, trigger the final promise
            resolve(whateverValue);
          },
          function onError(err) {
            // Fail everything if one of the requests fails, may not be
            // the right thing depending on your requirements
            reject(err);
          });
    }
    // Kick off the async work
    recurse();
  });
}

doSomethingAsync().then(
function final()
{
    //finishing code
});

再帰が発生する場所を再配置して、毎回新しいpromiseを再作成しないようにしました。したがって、ネストされたrecurse()関数は、外部レベルではなく、ネストされたrecurse()関数になりました。

于 2012-09-06T22:50:58.070 に答える
1

Promise.join()。done()パターンを使用する必要があります。Promisesの配列をjoin()に渡します。これは、この場合はxhr呼び出しのコレクションになります。join()は、すべてのxhr Promisesが完了した場合にのみdone()を呼び出します。一連の結果がdone()に渡され、それを繰り返して、新しいPromise.join()。done()呼び出しでやり直すことができます。このアプローチを使用する場合、避けるべきことは、join()に渡されたPromiseの1つが失敗した場合、操作全体がエラー状態として扱われることです。

申し訳ありませんが、今はコードをスタブ化する時間がありません。機会があれば、後でやってみます。しかし、これを再帰関数に挿入して、動作させることができるはずです。

于 2012-09-05T23:28:19.860 に答える
0

さて、私は問題を解決しました。私の再帰関数はデータを誤って解釈していたため、再帰を停止することはありませんでした。Promise のチェーン構造をまだ完全には把握していないので、スクリーンキャストを必ず見ます。

于 2012-09-06T00:08:43.290 に答える