Angular.js: Unterstützt asynchrones module.run()

Erstellt am 13. Sept. 2013  ·  62Kommentare  ·  Quelle: angular/angular.js

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.

Lots of comments won't fix feature

Hilfreichster Kommentar

jfcfxekzl5m
Einfache Funktion, aber zu schwer zu implementieren. 😕

Alle 62 Kommentare

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:

  • Gesundheitschecks
  • Erstellt das Produzierte für $rootElement
  • Erstellt den Injektor
  • Kompiliert und verknüpft die $rootElement

Darüber hinaus sind die Schritte beim Erstellen des Injektors die folgenden:

  • Durchlaufen des Abhängigkeitsmodulbaums und

    • Modulinitialisierung, die die Modulkonstanten, -werte, -anbieter und andere Dinge registrieren würde

    • Ausführen der Konfigurationsfunktionen

    • Sammle die run Funktionen für später

  • Führen Sie alle run Funktionen aus

Es gibt einige wichtige Punkte:

  • Alle run Blöcke werden ausgeführt, bevor $rootElement kompiliert wird
  • Es gibt keine Digest-Zyklen im Injektor-Erstellungsprozess, der erste Digest-Zyklus findet während der anfänglichen Kompilierung von $rootElement
  • $q löst Versprechen während eines Digest-Zyklus _nur_

Das ist:

  • Wenn es ein Modul mit einer 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).
  • Ein Konfigurationsblock kann kein Promise zurückgeben, da eine config Funktion mit Anbietern injiziert wird, nicht mit Instanzen

Welche 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

  • 1

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:

  • Verwenden Sie ngRoute oder ui-router mit Auflösungen und fügen Sie Ihren Anwendungsstartcode in die Route der obersten Ebene ein
  • Erstellen Sie Ihren eigenen asynchronen Bootstrap. siehe https://github.com/angular/angular.js/issues/4003#issuecomment -113842180
  • Verwenden Sie den neuen Komponentenrouter mit $onActivate in der Komponente der obersten Ebene

Wenn 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?

@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.

jfcfxekzl5m
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.

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen