2015-04-16 9 views
5

Für ein eckiges Projekt muss ich Versprechungen verschachteln und ich stoße auf Fälle, in denen ich nicht sicher bin, was ich tue. Hier ist eine meiner Code:Eckige bedingte Versprechen

return Action1().then(function (data) { 
    var defer = $q.defer(); 
    if (data.condition) { 
     $q.all([Action2(), Action3(), Action4()]).then(function() { 
      defer.resolve(); 
     }); 
    } else { 
     defer.reject("error_code"); 
    } 
    return defer.promise; 
}); 

Action1, Action2, Action3 und Action4 arbeiten Versprechen Funktionen. Es ist eine Menge Versprechungen und Aktionen hängen von den Bedingungen ab. Kann ich das tun und sicher sein, dass meine Hauptfunktion immer gelöst oder zurückgewiesen wird?

Ich lese, dass wir Versprechen innerhalb der Auflösungsfunktion übergeben können. Kann ich das und das ist das gleiche wie oben:

return Action1().then(function (data) { 
    var defer = $q.defer(); 
    if (data.condition) { 
     defer.resolve($q.all([Action2(), Action3(), Action4()]); 
    } else { 
     defer.reject("error_code"); 
    } 
    return defer.promise; 
}); 

Antwort

3

Nein, ist es nicht. Ihre erste Funktion würde für immer ausstehend bleiben, wenn einer von Action2(), Action3() oder Action4() "werfen" würde, und das Versprechen $q.all(…) zurückweisen - Ihr Deferred wird dann nie gelöst. Dies ist der häufigste Fehler des deferred antipattern, den Sie hier verwendet haben.

Ihre zweite Funktion mildert dies, ist aber immer noch unnötig kompliziert. Sie brauchen hier überhaupt kein Deferred! Einfach das ausge Versprechen direkt und verwenden $q.reject:

return Action1().then(function (data) { 
    if (data.condition) { 
     return $q.all([Action2(), Action3(), Action4()]); 
    } else { 
     return $q.reject("error_code"); 
    } 
}); 

Oder, wie dies in einem then Handler geschieht, können Sie auch throw "error_code" verwenden.

+0

Sie haben Ihre Antwort bearbeitet. Ich habe nach dem zweiten Teil gefragt, aber du antwortest mir während ich posten. Ich bin ein Anfänger mit Versprechungen. Ich lerne die Form (zögere mit Entschlossenheit und lehne ab) und ich benutzte sie überall in meinem Projekt. Vielen Dank für den Hinweis, dass ich direkt $ q oder Fehler verwenden könnte. – JeromeModi

1

Danke für Ihre Antwort, ich kann meinen Fehler auf der ersten Code-Version sehen. Ich denke, es ist der q.all, der mich stört.

Ich las das verzögerte Antipattern. Es heißt, dass wir keine verzögerten Objekte ohne Grund erstellen müssen. diese

Der einfache Fall ist:

return Action1().then(function() { 
    return $q.all([Action2(),Action3(), Action4()]);   
}); 

Aber aufgrund der if (data.condition) Ich kann es nicht tun. Ist mein zweiter Code der einzige Weg, es zu tun? Bin ich in einem Fall oder muss ich aufschieben?

Es spricht von "Promistification", aber mit Angular weiß ich nicht, ob es eine gute Sache ist (libs scheinen nicht gepflegt).

Prost,

+0

Ja, Sie sollten nur für die Promistification Deferred verwenden. Obwohl die beiden am häufigsten verwendeten asynchronen Methoden '$ http' und' $ timeout' bereits in eckig sind, geben sie Versprechen zurück, so dass Sie sie selten brauchen. – Bergi

+0

In Angular 1.3 habe ich gesehen, dass sie eine neue Syntax für den Konstruktor $ q einführen. Was denkst du darüber? Ist es eine gute Praxis, es zu benutzen? – JeromeModi

+1

Ein Recht, ein Versprechen Konstruktor. Ja, es ist eine gute Methode, es anstelle von Aufschub zu verwenden, es ist der neue Standard für Versprechungen. Aber das "latente Antipattern" ist immer noch das gleiche, vielleicht als "Verheißungskonstruktor Antipattern". Verwenden Sie keinesfalls, wenn die Funktion, mit der Sie arbeiten, bereits eine Rückgabe verspricht. – Bergi