2017-12-12 3 views
1

Ich habe Probleme mit jQuery.Deferred.prototype.then, , so entschied ich mich zu jQuery Testsuite zu überprüfen, ob ich richtig das Verhalten von verstehen diese Methode. Der Test, der am besten zu meinem Problem ist, ist die folgende, von Release 3.2.1:jQuery.Deferred.prototype.then: gibt ein Objekt mit Verhalten, das ich nicht verstehe

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

Hinweis:

  • Das Deferred Objekt wird auf der Leitung abgelehnt 153.
  • done wird in den Zeilen 144 und 164 aufgerufen. Ich bin nicht so vertraut mit QUnit, aber es ist ziemlich klar zu mir, dass der Test fehlschlägt, es sei denn werden die Callbacks, die an done übergeben werden, tatsächlich ausgeführt.
  • Die Rückrufe, die an done übergeben werden, sollten genau dann ausgeführt werden, wenn das Deferred Objekt aufgelöst, nicht zurückgewiesen wird. (Das ist mein Verständnis der Deferred documentation, sowieso.)

Aber die oben genannten drei Punkte können nicht alle richtig sein!

Beide Aufrufe an done werden an einem Objekt vorgenommen, das von jQuery.Deferred.prototype.then zurückgegeben wird. Ich kann den Code erklären, wenn ich setze, dass in Promise Objekt zurückgegeben von then, der endgültige Status ist anders als der Status des ursprünglichen Deferred. Ich kann jedoch keinen Hinweis darauf in der jQuery Dokumentation finden.

Auf meine Frage so kurz wie möglich gestellt: wenn der Code, den ich oben verlinkt habe ausgeführt wird, werden die Rückrufe , die done ausgeführt übergeben werden, und wenn ja, warum?

UPDATE

Hier ist der Code, den ich oben verlinkt (mit wenigen Kommentare hinzugefügt Zeilennummern angeben):

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

Es stellt sich heraus dass das Verhalten von then mit der Veröffentlichung von jQuery 3 im Juni 2016 geändert wurde. Nach einem post auf dem jQuery Blog, die neue Version der Ankündigung:

Die Auflösung Zustand eines von .then erstellt Latente() wird nun kontrolliert durch seine Rückrufe-Ausnahmen werden Abstoßungswerte und nicht-thenable kehrt werden Erfüllung Werte . Zuvor wurden Rückgaben von Ablehnungshandlern Ablehnungswerte.

Die für then wurde noch nicht aktualisiert.

+0

'then' wird aufgerufen, wenn" zurückgestelltes Objekt aufgelöst, zurückgewiesen "wird, ein anderes' Versprechen' zurückgegeben wird, was nicht mehr "abgelehnt" wird, also wird "erledigt" – Peter

+0

Ich persönlich empfehle, zu vergessen, dass 'done()' überhaupt existiert und verwenden Sie 'then()' und 'catch()', da die in jQuery 3 verzögerten Antworten A + konform sind. – charlietfl

+0

Bitte fügen Sie den relevanten Testcode direkt in Ihre Frage ein. Externe Links zu dem Code, der für die Frage relevant ist, haben die Angewohnheit, sich zu ändern oder zu brechen, wodurch die Frage als dauerhafte Referenz wertlos wird. Der externe Link ist OK, um als Quelle für andere Informationen da zu sein, aber der Kerncode, um den sich die Frage dreht, sollte IN der Frage selbst sein. – jfriend00

Antwort

2

Das latente Objekt 153.

auf Linie abgelehnt

Dies ist ein ziemlich schrecklich Test, auf einmal viele Dinge zu tun. Es gibt viele Zurückbehalte und viele Versprechen, von denen einige völlig unabhängig voneinander sind.

Beachten Sie, dass auf der Linie 153, die defer latenten abgelehnt, die einen befestigt .fail Rückruf haben, .then Rückrufe befestigt (die piped erstellt) und mehr .then in Leitung 153 selbst angebracht Rückrufe.

erledigt ist in den Zeilen 144 und 164 aufgerufen. Ich bin nicht so vertraut mit QUnit, aber es ist ziemlich klar für mich, dass der Test fehlschlagen wird, wenn die Rückrufe, die übergeben werden, tatsächlich ausgeführt werden.

Nein. Sie dürfen die zurückgestellte Methode .done und die ausgeführten Callbacks von QUnit nicht verwechseln. Tatsächlich gibt es drei QUnit-Rückrufe, die in dem done-Feld gespeichert sind, wobei jedes von ihnen durch assert.async() erzeugt wird.

Die an done übergebenen Callbacks sollten genau dann ausgeführt werden, wenn das verzögerte Objekt aufgelöst, nicht zurückgewiesen wird.

Ja, genau das passiert. Beachten Sie, dass die .done Anrufe in den Zeilen 144 und 164 sind auf den abgelehnten defer nicht aus latenten, sondern auf die piped Versprechen und eine anderen anonymen Versprechen von .then(null, jQuery.noop) erstellt. Diese Versprechungen sind nicht abgelehnt, sie sind mit dem Ergebnis des onrejected Rückrufs erfüllt, die als zweites Argument an den jeweiligen .then Aufruf übergeben wurden.

+0

über die „drei QUnit Rückrufe in dem getan Array gespeichert ": Ja, das habe ich perfekt verstanden. Es gab keine Verwirrung von meiner Seite. Über deinen letzten Absatz: Das ist die Antwort, die ich brauchte.Ich habe meinem Beitrag in "UPDATE 2" zusätzliche Informationen hinzugefügt. –

Verwandte Themen