2017-05-03 3 views
-1

Ich versuche zu verstehen, wie Promises mit jQuery funktioniert. dies ist mein Sandkasten:jQuery Zurückgestellt/Versprechen

function test1() { 
     var deferred = $.Deferred() 
     setTimeout(function() { 
      deferred.resolve(1); 
      //deferred.reject(2); 
     }, 2000); 
     return deferred.promise(); 
    } 

    function test2() { 
     var deferred = $.Deferred() 
     setTimeout(function() { 
      deferred.resolve(2); 
      // deferred.reject(2); 
     }, 1000); 
     return deferred.promise(); 
    } 

    function doTest(){ 
     $.when(test1()).then(
      function (a) { 
       console.log('test1 finished', a) 
       return test2(); 
      }, 
      function (a) { 
       console.log('something failed in test1', a) 
      } 
     ).then(
      function (b) { 
       console.log("test2 finished", b); 
      }, 
      function (b) { 
       console.log("something failed in test1", b); 
      } 
     ); 
    }  

Es funktioniert wie erwartet - Schriftfelter:

test1 fertig 1

test2 2

beendet Aber wenn ich es ändern, wie unten :

 function test1() { 
     var deferred = $.Deferred() 
     setTimeout(function() { 
      // deferred.resolve(1); 
      deferred.reject(2); 
     }, 2000); 
     return deferred.promise(); 
    } 

    function test2() { 
     var deferred = $.Deferred() 
     setTimeout(function() { 
      deferred.resolve(2); 
      // deferred.reject(2); 
     }, 1000); 
     return deferred.promise(); 
    } 

es schreiben zu trösten:

etwas versagt in test1 2

test2 undefined fertig

, was nicht wahr ist, weil test2 nicht einmal ausgeführt worden sind.

Ich erwarte, dass "test2 fertig undefined" nicht angezeigt werden sollte.

Ich denke, etwas ist in der Sekunde dann falsch, aber was?

+0

Sie müssen entweder "test2" im Fehlerhandler aufrufen, oder Sie müssen den "test 2 finished" -Logging-Ergebnishandler nur auf das 'test2()' Versprechen installieren, oder Sie müssen dies nicht tun Fang den Fehler davor. – Bergi

+0

Hört sich an, als ob Sie in jQuery 1.x/2.x etwas über Verzögerte/Versprechen gelernt haben und jetzt 3.x verwenden, das sich anders verhält (aka richtig). In 3.x wird standardmäßig ein catch-Handler (2. Argument von '.then()') abgefangen - die Versprechungskette setzt ihren Erfolgspfad fort, es sei denn, es wird ein Fehler ausgelöst/erneut ausgelöst oder eine Versprechung zurückgegeben, die (eventuell) zurückgewiesen wird . –

Antwort

0

Ihr Problem ist eigentlich in der OnRejected-Funktion der ersten then. Insbesondere, weil Sie "einen Wert zurückgeben" (undefiniert), dann behandelt der nächste then Handler in der Kette dies als erfüllt Versprechen.

$.when(test1()).then(
     function (a) { 
      console.log('test1 finished', a) 
      return test2(); 
     }, 
     function (a) { 
      console.log('something failed in test1', a) 
      // Your problem is here. 
     } 
    ).then(
     function (b) { 
      console.log("test2 finished", b); 
     }, 
     function (b) { 
      console.log("something failed in test1", b); 
     } 
    ); 

Dies kann in einigen Fällen nützlich sein:

$.when(riskyFunction()).then(
    function (value) { 
    return processValue(value); 
    }, function (error) { 
    console.log(error); 
    return defaultValue;   // This lets you recover... 
    }).then(function (value2) { 
    return processValue2(value2); // so this handler runs regardless of 
            // riskyFunction's return value. 
    }); 

Im Vergleich zu synchronen Code entspricht dies einem schmalen try Block:

try { 
    a = test1(); 
    b = test2(); 
} catch (e) { 
    console.log('something failed in test1', a) 
} 
console.log("test2 finished", b); // this runs even if test1 or test2 fails, 
            // but in those cases b is undefined! 

Stattdessen sollten Sie Ihre Fehlerhandler entfernen und fangen Sie Fehler am Ende oder mindestens return $.reject(a) oder throw a, um die Fehlerkette in Ihremzu verfolgenHandler.