2017-03-21 3 views
0

기본적으로 두 개의 REST 단계가있는 시퀀싱 기능이 있습니다 (단계 1과 2). 나는 다음과 같이 처리합니다. step1을 호출하고 실패한 후 핸들러를 그 다음에 두 번째 호출이 나옵니다. step2는 자체 실패하고 핸들러가 있습니다.Jquery Deferreds - 두 번째가 예기치 않게 호출되는 데 실패 함

self.step1() 
    .fail(self.onStep1Fail.bind(self)) 
    .then(self.onStep1Done.bind(self)) 
    .then(self.step2.bind(self)) 
    .fail(self.onStep2Fail.bind(self)) 
    .then(self.onStepDone.bind(self)); 

이 시퀀스를 읽으려면 step1이 호출되고 실패하면 step1의 fail 메서드가 호출됩니다. step1이 성공하면 step1Done 및 step2가 차례로 호출되고 step2는 step2Fail 또는 Step2Done이 호출되는지 여부를 판별합니다.

하지만 step1이 실패 할 때 어떤 이유로 Step1Fail과 Step2Fail이 호출되고 있습니다. 이는 예상치 못한 결과입니다. 아무도 이유를 아나요? 또한 step2Fail이 step2가 실제로 수행 된 후에 만 ​​호출되도록하려면 어떻게 이것을 변경해야합니까?

나는 좀 다음과 같은 방법을 사용하여이 달성 :

var handled = false; 

    function onCatch(handler) { 
     if (!handled) { 
      handled = true; 
      handler.call(self, Array.prototype.slice.call(window.Array.apply(null, arguments), 1)); 
     } 
     return $.Deferred().reject().promise(); 
    } 

    self.step1() 
     .catch(onCatch.bind(self, self.step1Fail)) 
     .then(self.step1Done.bind(self)) 
     .then(self.step2.bind(self)) 
     .catch(onCatch.bind(self, self.step2Fail)) 
     .then(self.step2Done.bind(self)); 

하지만이에 대한 간단한 접근 방법이 있는지 찾고 있습니다.

답변

0

fail은 단순히 콜백 체이닝 (callback chaining)없이 실패 처리기를 부착합니다. 지연된 입력을 반환합니다.

step1()이 실패하면 전체 체인이 작동하므로 체인의 모든 약속이 거부됩니다. 그리고 귀하의 경우 모든 약속의 실패 처리자가 실행됩니다 onStep1FailonStep2Fail. 만 step2이 실행될 때 호출에 onStep2… 핸들러를 원하는 경우

, 전체 체인에 넣어하지 않습니다

self.step1() 
.fail(self.onStep1Fail.bind(self)) 
.then(self.onStep1Done.bind(self)) 
.then(function(step1doneResult) { 
    return self.step2(step1doneResult) 
    .fail(self.onStep2Fail.bind(self)) 
    .then(self.onStepDone.bind(self)); 
}); 

그리고 난에 대해 전혀 fail 방법을 사용하지 않는 것이 좋습니다의 사슬 결합 부족. 그것은 읽을 점점 아니에요

self.step1() 
.then(self.onStep1Done.bind(self), self.onStep1Fail.bind(self)) 
.then(function(step1handlerResult) { 
    return self.step2(step1handlerResult) 
    .then(self.onStepDone.bind(self), self.onStep2Fail.bind(self)); 
}); 
+0

, 약속의 힘은 그들이 콜백처럼 중첩 대신 선형 체인이다 : 대신, then의 두 번째 매개 변수를 사용합니다. 물론, 모든 단계에서 성공/실패 구분을하고 싶다면,'if' /'else' 브랜치처럼 중첩시켜 - 중첩 [블록] (https://en.wikipedia.org/wiki/Block_ (프로그래밍))은 구조화 된 프로그래밍에서 완전히 자연 스럽습니다. – Bergi

+0

감사! 그래서 그때가 예상됩니다! 가능한 한 많이 겹치기를 피하려고했습니다. 코드를 초과하여 읽을 수없는 코드를 만들었습니다. 특히 더 많은 단계가 진행되는 경우 특히 그렇습니다. 또한 나는 보통 실패하기 위해 캐치를 선호한다. –

+0

네, ['catch'] (http://api.jquery.com/deferred.catch/) (jQuery 3부터 사용 가능합니다)는 괜찮습니다.하지만''fail''과 근본적으로 다릅니다. – Bergi

관련 문제