2016-07-22 23 views
1

私は以下のコードを書いています。 makeRequestが呼び出され、xhrステータスが0のときに再試行したいと思います。問題は正しい約束を解決できないため、再試行ロジックはn番目の試行で正しい応答をフェッチしますが、呼び出し元メソッドに伝播できません。ステータス0の約n回の再帰的な約束を返すxhrリクエストを再試行する方法

この問題を解決するにはどうすればよいですか?ここで

var makeRequest = function(method, urlToBeCalled, payload) { 
    var deferred = $q.defer(); 
    var xhr = new XMLHttpRequest(); 
    xhr.open(method, encodeURI(urlToBeCalled), true); 
    setHttpRequestHeaders(xhr); // set headers 
    var response; 
    xhr.onload = function() { 
    if (xhr.status === 200 && xhr.readyState === 4 && xhr.getResponseHeader('content-type') !== 
     'text/html') { 
     try { 
     response = JSON.parse(xhr.response); 
     deferred.resolve(response); 
     } catch (e) { 
     deferred.reject(e); 
     } 
    } else if (xhr.status === 0) { 
     // retry here; 
     deferred.resolve(makeRequest(method, urlToBeCalled, payload)); 
    } else { 
     try { 
     response = JSON.parse(xhr.response); 
     deferred.reject(response); 
     } catch (e) { 
     deferred.reject(xhr.response); 
     } 
    } 
    }; 
    xhr.onerror = function() { 
    deferred.reject(xhr.response); 
    }; 
    xhr.send(payload); 
    return deferred.promise; 
}; 

答えて

0

は(***コメントを参照してください)私はそれにアプローチしたい方法は次のとおりです。

var makeRequest = function(method, urlToBeCalled, payload) { 
    var deferred = $q.defer(); 
    var retries = 4;      // *** Counter 
    run();        // *** Call the worker 
    return deferred.promise; 

    // *** Move the actual work to its own function 
    function run() { 
     var xhr = new XMLHttpRequest(); 
     xhr.open(method, encodeURI(urlToBeCalled), true); 
     setHttpRequestHeaders(xhr); 
     xhr.onload = function() { 
      if (xhr.status === 200 && xhr.readyState === 4 && xhr.getResponseHeader('content-type') !== 'text/html') { 
       try { 
        response = JSON.parse(xhr.response); 
        deferred.resolve(response); 
       } catch (e) { 
        deferred.reject(e); 
       } 
      } else if (xhr.status === 0) { 
       // retry 
       if (retries--) {   // *** Recurse if we still have retries 
        run(); 
       } else { 
        // *** Out of retries 
        deferred.reject(e); 
       } 
      } else { 
       // *** See note below, probably remove this 
       try { 
        response = JSON.parse(xhr.response); 
        deferred.reject(response); 
       } catch (e) { 
        deferred.reject(xhr.response); 
       } 
      } 
     }; 
     xhr.onerror = function() { 
      deferred.reject(xhr.response); 
     }; 
     xhr.send(payload); 
    } 
}; 

サイドノート:あなたの最初のif本文の内容と最終elseが同一であるように思われます。私は全体onloadリキャストと思う:あなたのコメントを再

xhr.onload = function() { 
    if (xhr.readyState === 4) { 
     // It's done, what happened? 
     if (xhr.status === 200) { 
      if (xhr.getResponseHeader('content-type') !== 'text/html') { 
       try { 
        response = JSON.parse(xhr.response); 
        deferred.resolve(response); 
       } catch (e) { 
        deferred.reject(e); 
       } 
      } else { 
       // Something went wrong? 
       deferred.reject(e); 
      } 
     } else if (xhr.status === 0) { 
      // retry 
      if (retries--) {   // *** Recurse if we still have retries 
       run(); 
      } else { 
       // *** Out of retries 
       deferred.reject(e); 
      } 
     } 
    } 
}; 

これは私の現在の問題を解決しないだけに追加されたすべての約束を解決する方法がありますそれらのいずれかが解決された場合はスタックを呼び出しますか?

はい:角の$q(私はそれはあなたが使用しているものだと仮定)であることを行うには、あなたは自分の繰延オブジェクトにresolveにあなたが戻って再帰呼び出しから取得する約束を渡すことができます:それは約束ですので、その延期は、その約束が何をするかに基づいて決済され、解決または拒否されるのを待つことになる。あなたがチェーンのあらゆるレベルでこれを行う場合は、解像度がチェーンまで自分の道を働く:

angular.module("mainModule", []).controller(
 
    "mainController", 
 
    function($scope, $q, $http) { 
 
    test(true).then(function() { 
 
     test(false); 
 
    }); 
 

 
    function test(flag) { 
 
     log(flag ? "Testing resolved" : "Testing rejected"); 
 
     return recursive(3, flag) 
 
     .then(function(arg) { 
 
      log("Resolved with", arg); 
 
     }) 
 
     .catch(function(arg) { 
 
      log("Rejected with", arg); 
 
     }); 
 
    } 
 

 
    function recursive(count, flag) { 
 
     log("recursive(" + count + ", " + flag + ") called"); 
 
     var d = $q.defer(); 
 
     setTimeout(function() { 
 
     if (count <= 0) { 
 
      // Done, settle 
 
      if (flag) { 
 
      log("Done, resolving with " + count); 
 
      d.resolve(count); 
 
      } else { 
 
      log("Done, rejecting with " + count); 
 
      d.reject(count); 
 
      } 
 
     } else { 
 
      // Not done, resolve with promise from recursive call 
 
      log("Not done yet, recursing with " + (count - 1)); 
 
      d.resolve(recursive(count - 1, flag)); 
 
     } 
 
     }, 0); 
 
     return d.promise; 
 
    } 
 
    } 
 
); 
 

 
function log() { 
 
    var p = document.createElement('pre'); 
 
    p.appendChild(
 
    document.createTextNode(
 
     Array.prototype.join.call(arguments, " ") 
 
    ) 
 
); 
 
    document.body.appendChild(p); 
 
}
pre { 
 
    margin: 0; 
 
    padding: 0; 
 
}
<div ng-app="mainModule"> 
 
    <div ng-controller="mainController"></div> 
 
</div> 
 
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>

あなたはJavaScriptを自身の約束と同じことを行うことができます

test(true).then(function() { 
 
    test(false); 
 
}); 
 

 
function test(flag) { 
 
    log(flag ? "Testing resolved" : "Testing rejected"); 
 
    return recursive(3, flag) 
 
    .then(function(arg) { 
 
     log("Resolved with", arg); 
 
    }) 
 
    .catch(function(arg) { 
 
     log("Rejected with", arg); 
 
    }); 
 
} 
 

 
function recursive(count, flag) { 
 
    log("recursive(" + count + ", " + flag + ") called"); 
 
    return new Promise(function(resolve, reject) { 
 
    setTimeout(function() { 
 
     if (count <= 0) { 
 
     // Done, resolve with value 
 
     if (flag) { 
 
      log("Done, resolving with " + count); 
 
      resolve(count); 
 
     } else { 
 
      log("Done, rejecting with " + count); 
 
      reject(count); 
 
     } 
 
     } else { 
 
     // Not done, resolve with promise 
 
     // from recursive call 
 
     log("Not done yet, recursing with " + (count - 1)); 
 
     resolve(recursive(count - 1, flag)); 
 
     } 
 
    }, 0); 
 
    }); 
 
} 
 

 
function log() { 
 
    var p = document.createElement('pre'); 
 
    p.appendChild(
 
    document.createTextNode(
 
     Array.prototype.join.call(arguments, " ") 
 
    ) 
 
); 
 
    document.body.appendChild(p); 
 
}
pre { 
 
    margin: 0; 
 
    padding: 0; 
 
}

+0

Doh!上記の「再試行中」が表示されない場合は、リフレッシュを実行してください。 –

+0

ありがとうございます。これは私の現在の問題を解決しますが、それらのいずれかが解決された場合にスタックを呼び出すために追加されるすべての約束を解決する方法がありますか? – arbghl

+0

@arbghl:はい、実際には本当に簡単です。あなたは約束で「解決」を呼びます。あなたがそれを呼び出す約束は、その約束に基づいて解決または拒否されます。上記の例を追加しました。 –

関連する問題