2016-07-22 1 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); 
    } 
}; 

사이드 참고 : 최종 else이 동일하게 나타나는 초기 if 몸의 내용과를. 나는 전체 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>

당신은 자바 스크립트를 자신의 약속과 같은 일을 수행 할 수 있습니다

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 : 예 - 사실 쉽습니다. 당신은 약속으로'해결 '이라고 부르면됩니다. 당신이 약속 한 약속은 그 약속에 따라 해결되거나 거부 될 것입니다. 위의 예제를 추가했습니다. –

관련 문제