Wir möchten ein paar $http-Aufrufe im Modul-Run-Block absetzen, idealerweise sollte der Lauf erst nach $http beendet werden und die Verarbeitung beendet ist, bevor die dom-Kompilierung stattfindet.
Das ist nicht so einfach, sollte aber geprüft werden.
Jasmine macht dies, indem sie ein Flag setzt, das die Funktion laufen lässt und auf den Callback wartet, bis das Flag auf true
wird oder bis ein Timeout ausgelöst wird.
Im Grunde ungefähr so:
var flag = false;
$http(...).success(flag = true);
$timeout(function () {
flag = true;
// Or add some error handling stuff here
}, 5000);
while (!flag) {};
Es ist nicht schön, sollte aber den Job machen. Der obige Code wurde nicht getestet, daher müssen Sie ihn möglicherweise ein wenig ändern. Es wird spät hier. Hoffentlich etwas, um Sie zu überstehen, bis etwas Schöneres kommt.
+1
Auf der anderen Seite führt dies jedoch dazu, dass mit Winkelanweisungen kein schicker Ladebildschirm gezeichnet werden kann ...
+1
Löst $routeProvider
mit resolve
das nicht? Vielleicht habe ich das Problem nicht verstanden...
Dies ist mehr für die Init-Unterstützung von asynchronen Modulen. In meinen aktuellen Projekten benötige ich dies jedoch nicht mehr.
@shahata $routeprovider
tut dies, aber nicht jeder Anwendungsfall für versprechende run
s verwendet Routen. In meinem Anwendungsfall ist es für ein Modul, das eine Direktive umschließt und nichts mit Routen zu tun hat.
+1
Überprüfen Sie, ob die Run-Funktion ein Promise zurückgibt, und fahren Sie dann erst fort, wenn es gelöst ist. da runBlocks
ein Array von Funktionen ist, sollte es überhaupt nicht schwer sein
+1
+1 peinlich, dass das ignoriert wurde
eine ahnung wann das landen wird? Es ist so frustrierend, Initialisierungsmaterial verschieben zu müssen, um es im Router aufzulösen, hauptsächlich weil der Initialisierungscode manchmal URL-unabhängig ist (auch bekannt als, muss für jede Art von URL initialisiert werden, die der Benutzer in Ihrem SPA ankommt).
Ich glaube nicht, dass Angle in Zukunft Verbesserungen erhalten wird. sie werden alle zu eckigen 2.0 . hinzugefügt
Wie lange bleibt die halbherzige Methode run
synchron? Es ist in Ordnung und verständlich, dass config
keine asynchronen Aufrufe unterstützt, da Sie keine Anbieter haben, die $http
Aufrufe durchführen, run
jedoch. Schauen Sie sich die Art von Hacks an, die das Fehlen dieser Funktion (die von Anfang an vorhanden sein sollte) verursacht
https://github.com/philippd/angular-deferred-bootstrap/blob/master/src/deferred-bootstrap.js
Es ist peinlich
+1
@btford untersucht , wie die Anwendungsfälle in diesem Zusammenhang über den neuen Router und nicht in
+1
+1
+1
+1
Das Hauptproblem, das wir haben, ist, dass $q
in einem Modul erstellt wird, das geladen wird, wenn die runBlocks ausgeführt werden. Dies bedeutet, dass wir irgendwie "einige" der Dienste (oder vielleicht Module) extrahieren und diese zuerst erstellen und dann einen zweiten Durchgang durchführen müssen, der den Rest der Module (und Dienste, Ausführungsblöcke usw.) lädt, nachdem $q hat erstellt worden.
@lgalfaso - vielleicht könntest du dies später in dieser Woche (oder in der nächsten) als Teil deiner $injector
Arbeit etwas genauer untersuchen?
Ich weiß, dass es nur eine Problemumgehung ist, aber ich habe normalerweise das Problem einer asynchronen Bootstrapping-Logik gelöst, indem ich einen eckigen UI-Router und einen abstrakten Root-Status in Kombination mit Auflösung verwendet habe. Der abstrakte Root-Zustand muss immer zuerst aufgelöst werden, daher ist er ein guter Ort, um Einstellungen zu laden, Ladeanimationen anzuzeigen usw.
Das wäre wirklich toll.
:+1:
Warten auf diesen Fix. Hoffe es kommt in 1.4
+1
Ich habe einen anderen Anwendungsfall: Ich muss meine simulierten Endpunkte beim Start mit einem $http-Aufruf initieren (um einige Daten zwischenzuspeichern) ...
+1
+1
bin auch gerade darüber gestolpert...
@petebacondarwin Ich denke, es wäre in
alternativ könnte $routeProvider einen konfigurierbaren Funktionsparameter anbieten, der das Rendern der anfänglichen Route aufschieben sollte.
+1
+1
Hier ist eine mögliche Problemumgehung: http://plnkr.co/edit/vi7mDjmD4NpZAoP7MVzr?p=preview
Die Idee ist, dass Angular Ihnen tatsächlich die Möglichkeit gibt, Ihren eigenen Injektor aus einer Reihe von Modulen zu erstellen. In diesem Fall habe ich das Kompilieren von $rootElement
verzögert, bis eine Reihe von Versprechungen ( resolves
) gelöst sind. Dies ist ein POC und es würde eine Reihe anderer Schnickschnack geben, die benötigt würden, um diese Produktion fertig zu machen. Abgesehen von allem anderen müssten Sie Fehler in den Auflösungen erkennen, anstatt sie nur zu schlucken.
+1
Dies ist hauptsächlich ein Leitfaden für alle, die es ausprobieren möchten; Derzeit macht der Bootstrap-Prozess Folgendes:
$rootElement
$rootElement
Darüber hinaus sind die Schritte beim Erstellen des Injektors die folgenden:
run
Funktionen für späterrun
Funktionen ausEs gibt einige wichtige Punkte:
run
Blöcke werden ausgeführt, bevor $rootElement
kompiliert wird$rootElement
$q
löst Versprechen während eines Digest-Zyklus _nur_Das ist:
run
Funktion gibt, die ein Promise zurückgibt und das Promise aufgelöst werden muss, bevor die App gestartet wird, dann gibt es Digest-Zyklen vor der ersten Kompilierung (dadurch können vorhandene Apps beschädigt werden).config
Funktion mit Anbietern injiziert wird, nicht mit InstanzenWelche Lösung auch immer diese Fälle behandeln muss
+1
irgendwelche Neuigkeiten?
Ich möchte nur einige Konfigurationseinstellungen laden, bevor die App wirklich startet.
+1
Ich würde einige asynchrone Daten nach dem Bootstrap laden, wenn alle meine Fabriken hochgefahren sind und vor dem Kompilieren.
@dagingaa : Ich denke, ich würde deine Lösung als Workaround wählen! Danke
Update auf @dagingaa : Die for-Schleife friert meine Browser ein, ist nicht gut ...
https://jsfiddle.net/tuxmachine/t4d63vnw/
So habe ich es für eine OAuth-Token-Implementierung gelöst, bei der ein erster Ajax-Aufruf aufgelöst werden musste, bevor der Rest der App initialisiert wurde.
Funktioniert jedoch nicht, wenn Sie mehrere asynchrone Ausführungsblöcke haben
+1
+1
+1
Es ist zwei Jahre her, dass das Thema eröffnet wurde und es gibt immer noch keine gute Lösung
@vladmiller Es gibt Lösungen, aber vielleicht fühlen Sie sich nicht gut:
$onActivate
in der Komponente der obersten EbeneWenn Sie nicht-triviale Anwendungsarbeit in .run
Blöcke packen, ist es schwierig, Ihren Code zu testen. Es ist also nicht etwas, was wir fördern wollen. Dies in die Ice Box zu verschieben, da wir wahrscheinlich nicht implementieren werden.
@petebacondarwin Ich würde dir nicht zustimmen; Jeder erwartet, dass Angluar einfach und intuitiv ist, stattdessen müssen Sie entweder Ihr eigenes asynchrones Bootstrap-Modul oder ein Bootstrap-Modul an anderer Stelle implementieren. Das macht Winkel meiner Meinung nach komplexer.
Können Sie auch erklären, was Sie meinen, wenn Sie sagen, dass asynchroner Code in .run
das Testen erschwert?
Entschuldigung für meinen vorherigen unhöflichen Kommentar.
Vielen Dank
@petebacondarwin Ich .run
Blocks ausgeführt wird oder nicht. Wenn Code aufgrund von Workarounds für den Mangel an asynchroner Ausführung außerhalb des Winkels vorhanden ist, ist ein Test fast unmöglich
Wie geht's?
Ein anderer Ansatz: http://plnkr.co/edit/8XGSNOzzRGvgNSSnXx3M?p=preview
@petebacondarwin- Lösung hat bei mir funktioniert
Da es Problemumgehungen gibt und die Unterstützung von asynchronen Ausführungsblöcken den Bootstrap komplexer machen würde, glaube ich nicht, dass wir diese Funktion implementieren werden.
Einfache Funktion, aber zu schwer zu implementieren. 😕
+1 für diese Funktion
+1
+1
@petebacondarwin- Lösung funktioniert gut.
+1. :(
+1
+1
+1
+1
Wir werden dies nicht tun.
+100, alle Workarounds sind schrecklich.
@Eduardo-Julio - wir werden dieses Feature nicht implementieren, da es den Bootstrap von AngularJS-Anwendungen viel komplexer machen würde. Das Hinzufügen weiterer +
s wird nicht helfen.
Hilfreichster Kommentar
Einfache Funktion, aber zu schwer zu implementieren. 😕