2017-05-04 4 views
1

Ich habe 3 Funktionen, die Anrufe zu Backend-Systemen synchronisieren: fnOne, fnTwo, fnThree. Ich weiß, dass ich es nicht richtig mache, aber ich kann den richtigen Weg nicht finden.Verzögerte Versprechen - Ausführen von Funktionen nacheinander, nachdem jede abgeschlossen ist

Ich beginne durch, indem Sie versuchen, sie rufen Sie eine aus, nachdem jeweils ergänzt:

jedoch fnOne hat bereits ein latentes Objekt innerhalb davon und wenn das behoben ist es mein Versprechen zu lösen.

$.when(oController._fnOne()).done(function(){ 
    console.log("fn one complete"); 
}); 

Funktionen

_fnOne: function(){ 

    var oController = this; 

//when the deferred is done in _checkInstanceStatus, it is resolving the above, rather than the pDeferred in this function resolving the above. 
$.when(oController._checkInstanceStatus(oParams)).done(function(oStatusData) { 
     //does some stuff 
     return $.Deferred(function() { 
      var pDeferred = this; 
      //does a call for data and upon success i will resolve .. 
      pDeferred.resolve(); 
     }); 
    }); 
} 

andere Funktion

_checkInstanceStatus: function(oParams){ 
      return $.Deferred(function() { 
       var pDeffered = this; 
       //does a call for data and upon success i will resolve... 
       pDeffered.resolve(data); 

       }); 
      }); 
     }, 

Dann ist der Plan und die Kette um sie zu versuchen, damit sie eins nach dem anderen laufen, etwa so:

$.when(oController._fnOne()) 
.then(oController._fnTwo()) 
.then(oController._fnThree()) 
.done(function(){ 
    console.log("all complete!"); 
}); 
+0

Ich fürchte, es nicht genug Informationen in der Frage ist es, Ihnen eine solide Antwort zu geben. Was ist "ruft" zum Beispiel "fnOne"? Ist es etwas, das ein Versprechen zurückgibt? –

+0

@T.J.Crowder danke für Ihre Antwort, ist ein Anruf, wo es das Backend-System für Daten aufruft, ich bin das Auflösen der verzögerte, nachdem dieser Aufruf erfolgreich beendet hat pDeferred.resolve(); – neeko

+0

Dieser Aufruf an das Backend-System ist über was, '$ .ajax'? Nochmal: Gibt es ein Versprechen oder Aufschub, oder ...? –

Antwort

3

Ein paar Dinge:

  1. Sie müssen $.when nicht verwenden, wenn Sie eine einzelne Deferred übergeben.

  2. fnOne (und vermutlich auch die anderen) muss Rückkehr ein Versprechen/Latente, so dass Sie wissen, wann es abgeschlossen ist. Da es mit _checkInstanceStatus, die eine latente zurückgibt, kann es tun, dass durch die Verwendung then:

So fnOne könnte wie folgt aussehen:

fnOne: function() { 
    var oController = this; 
    return oController.__checkInstanceStatus(oParams).then(function(oStatusData) { 
     var pDeferred = $.Deferred(); 
     callAmazon(function() { 
      if (/*successful*/) { 
       pDeferred.resolve(); 
      } else { 
       pDeferred.reject(); 
      } 
     }); 
     return pDeferred.promise(); // Or just the Deferred if you like, but 
            // normally you want to share promises, not 
            // Deferred objects 
    }); 
} 

Beachten Sie, wie es kehrt das Ergebnis then Aufruf , das ist ein Versprechen, das durch den Aufruf then erstellt wird. Dieses Versprechen wird basierend auf dem Versprechen behoben, das Sie vom Handler then erhalten haben.

Sie würden das gleiche Muster mit den anderen Funktionen folgen.

Zur Kette sie eins nach dem anderen, dann würden Sie dies tun:

oController._fnOne() 
.then(oController._fnTwo)  // Notice no() on that, we're passing the 
.then(oController._fnThree)  // function in, not calling it. Same on this line. 
.then(function() { 
    console.log("all complete!"); 
}) 
.catch(function(error) { 
    // Do something about the error 
}); 

(Ich gehe davon aus _fnOne und fnOne die gleiche Funktion sind.)

ich ein relativ gehe mal davon Aktuelle Version von jQuery mit Promises-Unterstützung in Deferreds.


Randbemerkung: ich mit nativen Promises wechseln würde (mit einem polyfill ggf. alten Browsern zu unterstützen) anstatt mit jQuery Deferred, die ... gut hat es eine lange Geschichte hat und die API ist umständlich geworden.:-)

Mit nativer versprechen:

fnOne: function() { 
    var oController = this; 
    return oController.__checkInstanceStatus(oParams).then(function(oStatusData) { 
     return new Promise(function(resolve, reject) { 
      callAmazon(function() { 
       if (/*successful*/) { 
        resolve(); 
       } else { 
        reject(); 
       } 
      }); 
     }); 
    }); 
} 

Verwendung ist das gleiche (weil ich Versprechen APIs verwendet, die im ersten Beispiel zu latenten hinzugefügt wurden).

+1

Appologies, ein paar Tippfehler meinerseits Auch wenn ich versuche, den Code zu vereinfachen! Vielen Dank, das funktioniert gut !! Ich habe auch auf native Versprechungen umgeschaltet – neeko

+0

eine letzte Frage für Sie - wie würde ich Daten von einer Funktion zur nächsten in Folge übergeben? – neeko

+1

@neeko: Sie übergeben es als Argument an "resolve" und erhalten es als Parameter in der Zielfunktion. Zum Beispiel, wenn '_fnOne'' auflöst ("foo") ', mit der Kette über' _fnTwo's erster Parameter hat den Wert '" foo "'. :-) –

2

Es ist ziemlich schwierig, Ihre Funktion zu verstehen. So habe ich es einfach gemacht, 3 neue Funktionen mit 3 verschiedenen Möglichkeiten zu definieren, so dass Sie jquery deferred leichter verstehen können.

var funcOne = function() { 
    var defer = $.Deferred(); 
    $.ajax('/echo/json') 
    .then(function(data) { 
     console.log('func1', data); 
     return defer.resolve(data); 
    }); 
    return defer; 
} 

var funcTwo = function() { 
    console.log('begin call func 2'); 
    return $.ajax('/echo/json') 
    .then(function(data) { 
     console.log('func2', data); 
     return $.Deferred().resolve(data); 
    }); 
} 

var funcThree = $.ajax('/echo/json'); 

funcOne() 
    .then(funcTwo) 
    .then(funcThree) 
    .then(function(data) { 
    console.log('finally got func 3 data', data) 
    }); 

jsfiddle Link: https://jsfiddle.net/zmjLaznn/

Verwandte Themen