2017-12-12 11 views
1

jQuery.Deferred.prototype.then, 과 관련하여 문제가 발생했기 때문에 jQuery의 테스트 스위트를보고 의 동작을 올바르게 확인했는지 확인하기로 결정했습니다. 이 방법. 내 문제에 가장 관련 시험은 릴리스 3.2.1에서, 다음과 같다 :jQuery.Deferred.prototype.then : 이해할 수없는 동작을 가진 객체를 반환합니다.

https://github.com/jquery/jquery/blob/3.2.1/test/unit/deferred.js#L133-L168

참고 :

  • Deferred 객체가 줄에 거부 (153)
  • done은 144 번과 164 번 라인에서 호출됩니다. 저는 QUnit에 익숙하지 않지만, 에 대해서는 분명합니다. done에 전달 된 콜백이 실제로 실행됩니다.
  • 에 전달 된 콜백은 Deferred 개체 인 이 거부되었지만 해결 된 경우에만 실행되어야합니다.

(즉, Deferred documentation, 에 대한 이해는. 어쨌든이다) 그러나 위의 3 점은 모두 정확하지 않을 수 있습니다!

done에 대한 호출은 모두 jQuery.Deferred.prototype.then에 의해 반환 된 개체에서 수행됩니다. 나는 코드를 설명 할 수 있습니다. Promise 객체의 경우 then, 의 최종 상태가 원래 Deferred의 상태와 다릅니다. 그러나 jQuery 설명서에서 이에 대한 힌트를 찾을 수 없습니다.

는 간단히 가능한 내 질문을 넣어 : 이 나는 ​​위에 연결 한 코드가 실행될 때 만약 그렇다면, done에 전달되는 콜백 실행하고 있으며, 그 이유는 무엇입니까?

QUnit.test("jQuery.Deferred.then - filtering (fail)", function(assert) { 

     assert.expect(4); 

     var value1, value2, value3, 
       defer = jQuery.Deferred(), 
       piped = defer.then(null, function(a, b) { 
         return a * b; 
       }), 
       done = jQuery.map(new Array(3), function() { return assert.async(); }); 

     piped.done(function(result) { // Line 144 
       value3 = result; 
     }); 

     defer.fail(function(a, b) { 
       value1 = a; 
       value2 = b; 
     }); 

     defer.reject(2, 3).then(null, function() { // Line 153 
       assert.strictEqual(value1, 2, "first reject value ok"); 
       assert.strictEqual(value2, 3, "second reject value ok"); 
       assert.strictEqual(value3, 6, "result of filter ok"); 
       done.pop().call(); 
     }); 

     jQuery.Deferred().resolve().then(null, function() { 
       assert.ok(false, "then should not be called on resolve"); 
     }).then(done.pop()); 

     jQuery.Deferred().reject().then(null, jQuery.noop).done( // Line 164 
function(value) { 
       assert.strictEqual(value, undefined, "then fail callback can return undefined/null"); 
       done.pop().call(); 
     }); 
}); 

UPDATE 그것은 밝혀 2

: 여기 UPDATE

는 (줄 번호를 표시하기 위해 추가 된 몇 가지 의견) 내가 위의 링크 된 코드입니다 then의 동작이 2016 년 6 월 jQuery 3의 릴리스와 함께 변경되었습니다. post 01 새 릴리스를 발표 JQuery와 블로그에 23,516,:

A는() 이제 콜백-예외가 거부 값과 비 thenable 반환 하게 이행 값이 될 에 의해 제어되는 그 때는 만든 연기의 해결 상태 . 이전에는 거부 처리기 의 반환 값이 거부 값이되었습니다.

then에 대한 documentation은 아직 업데이트되지 않았습니다.

+0

''연기 된 객체가 해결되고 거절 될 때'then'이 호출되어'promise'를 반환하고'rejected'는 더 이상'done'이 실행되지 않을 때 – Peter

+0

개인적으로'done() 아마도'then()'과'catch() '를 사용하십시오. 왜냐하면 jQuery 3의 지연은 promises A +라고 추정되기 때문입니다. – charlietfl

+0

질문에 직접 관련 테스트 코드를 삽입하십시오. 질문과 관련된 코드로의 외부 링크는 시간이 지남에 따라 변화하거나 깨는 습관을 가지고있어이 질문을 영구적 인 참고 자료로 만들 수 있습니다. 외부 링크는 다른 정보의 출처로 존재하는 것이 좋지만 질문에 대한 핵심 코드는 질문 자체에 있어야합니다. – jfriend00

답변

2

이연 목적이 한 번에 많은 일을 꽤 끔찍한 테스트입니다 라인 (153)

에 거부됩니다. 많은 연기와 많은 약속들이 있습니다. 그들 중 일부는 서로 전혀 관련이 없습니다. 부착 .fail 콜백 (piped 생성) 첨부 .then 콜백을 가지고 선 (153)에, 이연 defer가 거부

통지, 및 라인 (153) 자체에 부착 된 더 .then 콜백.

done은 라인 144와 164에서 호출됩니다. 저는 QUnit에 익숙하지 않지만, done으로 전달 된 콜백이 실제로 실행되지 않으면 테스트가 실패합니다.

아니요. 지연된 .done 방법과 QUnit의 완료 콜백을 혼동해서는 안됩니다. 실제로 done 배열에 저장된 3 개의 QUnit 콜백이 있으며 각각은 assert.async()으로 생성됩니다.

지연된 개체가 확인되고 거부되지 않는 경우에만 완료로 전달되는 콜백이 실행되어야합니다.

예, 이것이 정확히 일어납니다. 144,164 번 줄에있는 .done 전화는 거절 된 defer 호가 아니라 piped 호 약속과 .then(null, jQuery.noop) 호로 작성된 또 다른 익명 성 약속에 적용됩니다. 이러한 약속은 이 아니며이 거부되었으므로 각각 .then 호출에 두 번째 인수로 전달 된 거부 된 콜백 결과로 충족됩니다.

+0

"완료된 배열에 저장된 세 개의 QUnit 콜백 정보 ": 예, 저는 이것을 완벽하게 이해했습니다. 내 부분에는 혼란이 없었습니다. 마지막 단락 정보 : 이것은 내가 필요한 대답입니다."UPDATE 2"에서 내 게시물에 보충 정보를 추가했습니다. –