Ich habe einige Beispiele für Facebook-Anmeldedienste gesehen, die Versprechen für den Zugriff auf die FB Graph-API verwendeten.
Beispiel 1 :
this.api = function(item) {
var deferred = $q.defer();
if (item) {
facebook.FB.api('/' + item, function (result) {
$rootScope.$apply(function () {
if (angular.isUndefined(result.error)) {
deferred.resolve(result);
} else {
deferred.reject(result.error);
}
});
});
}
return deferred.promise;
}
Und Dienste, die verwendet wurden, "$scope.$digest() // Manual scope evaluation"
als die Antwort erhalten wurde
Beispiel 2 :
angular.module('HomePageModule', []).factory('facebookConnect', function() {
return new function() {
this.askFacebookForAuthentication = function(fail, success) {
FB.login(function(response) {
if (response.authResponse) {
FB.api('/me', success);
} else {
fail('User cancelled login or did not fully authorize.');
}
});
}
}
});
function ConnectCtrl(facebookConnect, $scope, $resource) {
$scope.user = {}
$scope.error = null;
$scope.registerWithFacebook = function() {
facebookConnect.askFacebookForAuthentication(
function(reason) { // fail
$scope.error = reason;
}, function(user) { // success
$scope.user = user
$scope.$digest() // Manual scope evaluation
});
}
}
Die Fragen sind:
- Was ist der Unterschied in den obigen Beispielen?
- Was sind die Gründe und Fälle für die Nutzung des $ q- Dienstes?
- Und wie funktioniert es funktioniert ?
Antworten:
Dies ist keine vollständige Antwort auf Ihre Frage, aber hoffentlich hilft dies Ihnen und anderen, wenn Sie versuchen, die Dokumentation zum
$q
Dienst zu lesen . Ich habe eine Weile gebraucht, um es zu verstehen.Lassen Sie uns AngularJS für einen Moment beiseite legen und nur die Facebook-API-Aufrufe betrachten. Beide API-Aufrufe verwenden einen Rückrufmechanismus , um den Anrufer zu benachrichtigen, wenn die Antwort von Facebook verfügbar ist:
Dies ist ein Standardmuster für die Verarbeitung asynchroner Vorgänge in JavaScript und anderen Sprachen.
Ein großes Problem mit diesem Muster tritt auf, wenn Sie eine Folge von asynchronen Operationen ausführen müssen, wobei jede aufeinanderfolgende Operation vom Ergebnis der vorherigen Operation abhängt. Das macht dieser Code:
Zuerst wird versucht, sich anzumelden, und erst nachdem überprüft wurde, ob die Anmeldung erfolgreich war, wird die Anforderung an die Graph-API gesendet.
Selbst in diesem Fall, in dem nur zwei Operationen miteinander verkettet werden, wird es langsam chaotisch. Die Methode
askFacebookForAuthentication
akzeptiert einen Rückruf für Fehler und Erfolg. Was passiert jedoch, wenn diesFB.login
erfolgreich ist, aberFB.api
fehlschlägt? Diese Methode ruft densuccess
Rückruf immer auf, unabhängig vom Ergebnis derFB.api
Methode.Stellen Sie sich nun vor, Sie versuchen, eine robuste Folge von drei oder mehr asynchronen Vorgängen so zu codieren, dass Fehler bei jedem Schritt richtig behandelt werden und nach einigen Wochen für andere oder sogar für Sie lesbar sind. Möglich, aber es ist sehr einfach, diese Rückrufe einfach weiter zu verschachteln und dabei den Überblick über Fehler zu verlieren.
Lassen Sie uns nun die Facebook-API für einen Moment beiseite legen und nur die Angular Promises-API betrachten, die vom
$q
Dienst implementiert wurde . Das von diesem Dienst implementierte Muster ist ein Versuch, die asynchrone Programmierung wieder in etwas zu verwandeln, das einer linearen Reihe einfacher Anweisungen ähnelt, mit der Fähigkeit, einen Fehler in jedem Schritt des Weges zu "werfen" und ihn am Ende zu behandeln, semantisch ähnlich dem vertrautertry/catch
Block.Betrachten Sie dieses erfundene Beispiel. Angenommen, wir haben zwei Funktionen, wobei die zweite Funktion das Ergebnis der ersten verbraucht:
Stellen Sie sich nun vor, dass sowohl firstFn als auch secondFn lange dauern, sodass wir diese Sequenz asynchron verarbeiten möchten. Zuerst erstellen wir ein neues
deferred
Objekt, das eine Operationskette darstellt:Die
promise
Eigenschaft repräsentiert das endgültige Ergebnis der Kette. Wenn Sie ein Versprechen unmittelbar nach dem Erstellen protokollieren, sehen Sie, dass es sich nur um ein leeres Objekt handelt ({}
). Noch nichts zu sehen, gehen Sie weiter.Bisher ist unser Versprechen nur der Ausgangspunkt in der Kette. Fügen wir nun unsere beiden Operationen hinzu:
Die
then
Methode fügt der Kette einen Schritt hinzu und gibt dann ein neues Versprechen zurück, das das endgültige Ergebnis der erweiterten Kette darstellt. Sie können beliebig viele Schritte hinzufügen.Bisher haben wir unsere Funktionskette eingerichtet, aber es ist tatsächlich nichts passiert. Sie beginnen mit einem Aufruf
deferred.resolve
und geben den Anfangswert an, den Sie an den ersten tatsächlichen Schritt in der Kette übergeben möchten:Und dann ... passiert immer noch nichts. Um sicherzustellen, dass Modelländerungen ordnungsgemäß beobachtet werden, ruft Angular den ersten Schritt in der Kette erst auf, wenn das nächste Mal
$apply
Folgendes aufgerufen wird:Was ist also mit der Fehlerbehandlung? Bisher haben wir nur einen Erfolgshandler für jeden Schritt in der Kette angegeben.
then
akzeptiert auch einen Fehlerhandler als optionales zweites Argument. Hier ist ein weiteres, längeres Beispiel für eine Versprechenskette, diesmal mit Fehlerbehandlung:Wie Sie in diesem Beispiel sehen können, hat jeder Handler in der Kette die Möglichkeit, den Datenverkehr zum nächsten Fehlerhandler anstatt zum nächsten Erfolgshandler umzuleiten. In den meisten Fällen können Sie einen einzelnen Fehlerbehandler am Ende der Kette haben, aber Sie können auch Zwischenfehlerbehandler haben, die versuchen, eine Wiederherstellung durchzuführen.
Um schnell zu Ihren Beispielen (und Ihren Fragen) zurückzukehren, möchte ich nur sagen, dass sie zwei verschiedene Möglichkeiten darstellen, die rückruforientierte API von Facebook an Angulars Art der Beobachtung von Modelländerungen anzupassen. Das erste Beispiel umschließt den API-Aufruf mit einem Versprechen, das einem Bereich hinzugefügt werden kann und von Angulars Template-System verstanden wird. Der zweite Ansatz ist der Brute-Force-Ansatz, bei dem das Rückrufergebnis direkt auf den Bereich festgelegt und anschließend aufgerufen wird
$scope.$digest()
, um Angular auf die Änderung von einer externen Quelle aufmerksam zu machen.Die beiden Beispiele sind nicht direkt vergleichbar, da im ersten der Anmeldeschritt fehlt. Im Allgemeinen ist es jedoch wünschenswert, Interaktionen mit solchen externen APIs in separaten Diensten zu kapseln und die Ergebnisse als Versprechen an Controller zu liefern. Auf diese Weise können Sie Ihre Controller von externen Belangen trennen und sie einfacher mit Mock-Services testen.
quelle
then
Methoden ist die Verwendung$q.all
. Ein kurzes Tutorial dazu finden Sie hier .$q.all
ist geeignet, wenn Sie warten müssen, bis mehrere unabhängige asynchrone Vorgänge abgeschlossen sind. Es ersetzt nicht die Verkettung, wenn jede Operation vom Ergebnis der vorherigen Operation abhängt.return 'firstResult'
Teil in ändernreturn $q.resolve('firstResult')
, was ist der Unterschied?Dies ist der Plunk für Winkelversprechen MVP (Minimum Viable Versprechen) : http://plnkr.co/edit/QBAB0usWXc96TnxqKhuA?p=preview
Quelle:
(für diejenigen, die zu faul sind, um auf die Links zu klicken)
index.html
app.js.
(Ich weiß, dass es Ihr spezifisches Facebook-Beispiel nicht löst, aber ich finde folgende Ausschnitte nützlich)
Via: http://markdalgleish.com/2013/06/using-promises-in-angularjs-views/
Update 28. Februar 2014: Ab 1.2.0 werden Versprechen nicht mehr durch Vorlagen gelöst. http://www.benlesh.com/2013/02/angularjs-creating-service-with-http.html
(Plunker-Beispiel verwendet 1.1.5.)
quelle
Ein Zurückgestelltes repräsentiert das Ergebnis einer asynchronen Operation. Es stellt eine Schnittstelle bereit, die zum Signalisieren des Status und des Ergebnisses der von ihm dargestellten Operation verwendet werden kann. Es bietet auch eine Möglichkeit, die zugehörige Versprechen-Instanz abzurufen.
Ein Versprechen bietet eine Schnittstelle für die Interaktion mit dem zugehörigen Aufschub und ermöglicht so interessierten Parteien den Zugriff auf den Staat und das Ergebnis des aufgeschobenen Vorgangs.
Beim Erstellen eines Aufgeschobenen steht der Status aus und es wird kein Ergebnis angezeigt. Wenn wir den Zurückgestellten auflösen () oder ablehnen (), ändert sich sein Status in aufgelöst oder abgelehnt. Trotzdem können wir das damit verbundene Versprechen sofort nach dem Erstellen eines Aufschubs erhalten und sogar Interaktionen mit dem zukünftigen Ergebnis zuweisen. Diese Interaktionen treten erst auf, nachdem die Zurückstellung abgelehnt oder behoben wurde.
quelle
Verwenden Sie Versprechen innerhalb eines Controllers und stellen Sie sicher, dass die Daten verfügbar sind oder nicht
quelle