Angular.js: Soporte asincrónico module.run ()

Creado en 13 sept. 2013  ·  62Comentarios  ·  Fuente: angular/angular.js

Queremos emitir algunas llamadas $ http en el bloque de ejecución del módulo, idealmente, la ejecución debería finalizar solo después de que $ http y el procesamiento finalice antes de que ocurra la compilación de dom.

Lots of comments won't fix feature

Comentario más útil

jfcfxekzl5m
Característica simple pero demasiado difícil de implementar. 😕

Todos 62 comentarios

Esto no es tan fácil, pero debería analizarse.

La forma en que Jasmine hace esto es estableciendo una bandera, que permitirá que la función se ejecute y esperará la devolución de llamada hasta que la bandera se establezca en true , o hasta que se dispare un tiempo de espera.

Básicamente algo como esto:

var flag = false;
$http(...).success(flag = true);
$timeout(function () {
    flag = true;
    // Or add some error handling stuff here
}, 5000);
while (!flag) {};

No es bonito, pero debería hacer el trabajo. El código anterior no se ha probado, por lo que es posible que deba modificarlo un poco. Se hace tarde aquí. Con suerte, algo para ayudarte hasta que aparezca algo un poco más bonito.

+1

Sin embargo, en un segundo, esto conduce a la incapacidad de dibujar una pantalla de carga elegante utilizando directivas angulares ...

+1

¿No resuelve esto $routeProvider con resolve ? Quizás no entendí el problema ...

Esto es más para el soporte de inicio de módulo asíncrono. Dicho esto, ya no necesito esto en mis proyectos actuales.

@shahata $routeprovider hace esto, pero no todos los casos de uso para hacer promesas run s usan rutas. En mi caso de uso, es para un módulo que envuelve una directiva y no tiene nada que ver con las rutas.

+1

compruebe si la función de ejecución devuelve una promesa, luego solo proceda cuando se resuelva. dado que runBlocks es una matriz de funciones, no debería ser difícil en absoluto

+1

+1 vergonzoso que esto haya sido ignorado

¿Alguna idea de cuándo va a aterrizar esto? es muy frustrante tener que mover las cosas de inicialización para resolverlas en el enrutador, principalmente porque a veces el código de inicialización es independiente de la URL (también conocido como, debe inicializarse para cualquier tipo de URL que el usuario llegue a su SPA)

No creo que angular reciba mejoras a partir de ahora. todos se agregan a angular 2.0

¿Cuánto tiempo permanecerá sincrónico el método run medias? Está bien y es comprensible que config no admita llamadas asincrónicas, ya que no tiene proveedores que hagan llamadas $http , pero run sí. mire el tipo de hacks que causa la falta de esta característica (que debería haber estado desde el principio)
https://github.com/philippd/angular-deferred-bootstrap/blob/master/src/deferred-bootstrap.js

es vergonzoso

+1

@btford está analizando cómo los casos de uso relacionados con esto podrían ser compatibles a través del nuevo enrutador en lugar de dentro de los bloques de ejecución.

+1

+1

+1

+1

El principal problema que tenemos es que $q se crea dentro de un módulo que se está cargando cuando se ejecutan los runBlocks. Esto significa que tendríamos que extraer de alguna manera "algunos" de los servicios (o quizás módulos) y crearlos primero y luego tener una segunda pasada que cargue el resto de los módulos (y servicios, ejecutar bloques, etc.) después de que $ q haya sido creado.

@lgalfaso , ¿quizás podrías investigar esto un poco más como parte de tu trabajo $injector más adelante esta semana (o la próxima)?

Sé que es solo una solución, pero normalmente resolví el problema de tener alguna lógica de arranque asíncrono usando un enrutador de interfaz de usuario angular y tener un estado abstracto de raíz en combinación con resolver. El estado abstracto raíz siempre debe resolverse primero, por lo que es un buen lugar para cargar configuraciones, mostrar animaciones de carga, etc.

Esto sería genial.
: +1:
Esperando esta solución. Espero que llegue en 1.4

+1

Tengo otro caso de uso: necesito iniciar mis puntos finales simulados con una llamada $ http al inicio (para almacenar en caché algunos datos) ...

+1

+1

acaba de tropezar con esto también ...

@petebacondarwin creo que estaría bien continuar cargando todos los demás módulos, pero aplazar el inicio de la navegación inicial.

alternativamente, $ routeProvider podría ofrecer un parámetro de función configurable que debería posponer la representación de la ruta inicial.

+1

+1

Aquí hay una posible solución: http://plnkr.co/edit/vi7mDjmD4NpZAoP7MVzr?p=preview
La idea es que Angular te da la posibilidad de crear tu propio inyector a partir de un conjunto de módulos. En este caso, he retrasado la compilación de $rootElement hasta que se hayan resuelto un montón de promesas ( resolves ). Este es un POC y habría una serie de otras campanas y silbidos que serían necesarios para que esta producción esté lista. Aparte de cualquier otra cosa, necesitaría detectar errores en las resoluciones en lugar de simplemente tragarlos.

+1

Esta es principalmente una guía para quien quiera intentarlo; Actualmente, el proceso de arranque hace lo siguiente:

  • Controles de cordura
  • Crea el producido por $rootElement
  • Crea el inyector
  • Compila y vincula el $rootElement

En la parte superior, al crear el inyector los pasos son los siguientes:

  • Atravesando el árbol del módulo de dependencia y

    • Inicialización del módulo que registraría las constantes, valores, proveedores y otras cosas del módulo.

    • Ejecutando las funciones de configuración

    • Recolecte las funciones run para más tarde

  • Ejecute todas las funciones run

Hay algunos puntos clave:

  • Todos los bloques run se ejecutan antes de que se compile $rootElement
  • No hay ciclos de resumen en el proceso de creación del inyector, el primer ciclo de resumen es durante la compilación inicial de $rootElement
  • $q resuelve promesas durante un ciclo de resumen _only_

Este es:

  • Si hay un módulo que tiene una función run que devuelve una promesa y la promesa debe resolverse antes de que se inicie la aplicación, habrá ciclos de resumen antes de la compilación inicial (esto puede romper las aplicaciones existentes)
  • Un bloque de configuración no puede devolver una promesa ya que una función config se inyecta con proveedores, no con instancias

Cualquiera que sea la solución, necesita manejar estos casos

+1
¿hay noticias?
Solo quiero cargar algunas configuraciones de configuración antes de que la aplicación realmente comience.

+1

Cargaría algunos datos asíncronos después del arranque cuando todas mis fábricas estén funcionando y antes de la compilación.

@dagingaa : ¡Creo que elegiría su solución como solución alternativa! Gracias

  • 1

Actualización a @dagingaa : el bucle for congela mis navegadores, no es bueno ...

https://jsfiddle.net/tuxmachine/t4d63vnw/

Así es como lo resolví para una implementación de token de OAuth, que requería que se resolviera una llamada ajax inicial antes de inicializar el resto de la aplicación.

Sin embargo, no funcionará si tiene varios bloques de ejecución asíncronos

+1

+1

+1

Han pasado dos años desde que se abrió el problema y todavía no hay una buena solución.

@vladmiller Hay soluciones pero quizás no sientes que son buenas:

  • use ngRoute o ui-router con resuelve y coloque el código de inicio de su aplicación dentro de la ruta de nivel superior
  • cree su propio bootstrap asincrónico. ver https://github.com/angular/angular.js/issues/4003#issuecomment -113842180
  • use el nuevo enrutador de componentes con $onActivate en el componente de nivel superior

Poner el trabajo de la aplicación no trivial dentro de los bloques .run dificulta la prueba unitaria de su código. Por tanto, no es algo que queramos fomentar. Mover esto a la caja de hielo como algo que probablemente no implementemos.

@petebacondarwin No estoy de acuerdo contigo; todos esperan que angluar sea simple e intuitivo, en su lugar, debe implementar su propio módulo de arranque asíncrono o módulo de arranque en un lugar diferente. En mi opinión, esto hace que angular sea más complejo.

¿También puede explicar qué quiere decir cuando dice que el código asíncrono en .run hará que las pruebas sean más difíciles?

Disculpas por mi anterior comentario grosero.
Gracias

@petebacondarwin No veo cómo dificulta la prueba. Si coloca el código de inicialización en un servicio, puede simplemente ver / simular / comparar los resultados que espera del simulacro de backend http, independientemente de si se está ejecutando dentro de un bloque .run o no. el hecho de que el código exista fuera de angular debido a soluciones temporales por la falta de ejecución asíncrona es lo que hace que sea casi imposible de probar

¿Cómo va?

La solución

Dado que existen soluciones alternativas y el soporte de bloques de ejecución asíncrona agregaría complejidad al bootstrap, no creo que implementemos esta función.

jfcfxekzl5m
Característica simple pero demasiado difícil de implementar. 😕

+1 para esta función

+1

+1

La solución

+1. :(

+1

+1

+1

+1

No vamos a hacer esto.

+100, todas las soluciones son terribles.

@ Eduardo-Julio: no vamos a implementar esta función, ya que haría mucho más complejo el arranque de las aplicaciones AngularJS. Agregar más + s no ayudará.

¿Fue útil esta página
0 / 5 - 0 calificaciones