Cómo compartir el servicio entre dos módulos - @NgModule en angular no entre a los componentes?


En mi aplicación, tengo dos módulos bootstrap diferentes (@NgModule) que se ejecutan de forma independiente en una aplicación. No hay un módulo de bootstrap separado de bit angular app y ahora quiero que se comuniquen entre sí y compartan datos.

Sé a través del servicio @Injectable como proveedor en el módulo, puedo compartir datos en todos los componentes bajo @NgModule pero cómo compartiré datos entre dos módulos diferentes ( no componente dentro del módulo ).

¿Hay alguna forma en que un objeto de servicio puede se puede acceder en otro módulo? ¿Hay alguna forma de acceder al objeto de Servicio disponible en la memoria del navegador y usarlo en mi otro módulo angular?

Author: Aniruddha Das, 2016-10-17

5 answers

Puede crear una instancia de un servicio fuera de Angular y proporcionar un valor:

class SharedService {
  ...
}
window.sharedService = new SharedService();

@NgModule({
  providers: [{provide: SharedService, useValue: window.sharedService}],
  ...
})
class AppModule1 {}

@NgModule({
  providers: [{provide: SharedService, useValue: window.sharedService}],
  ...
})
class AppModule2 {}

Si una aplicación cambia el estado en SharedService o llama a un método que hace que un Observable emita un valor y el suscriptor está en una aplicación diferente al emisor, el código en el suscriptor se ejecuta en el NgZone del emisor.

Por lo tanto, cuando se suscriba a un observable en SharedService use

class MyComponent {
  constructor(private zone:NgZone, private sharedService:SharedService) {
    sharedService.someObservable.subscribe(data => this.zone.run(() => {
      // event handler code here
    }));
  }
}

Véase también Cómo crear modales de bootstrap dinámicamente como Angular2 componentes?

 6
Author: Günter Zöchbauer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:34:38

Según la versión final de Angular 2, los servicios proporcionados por un módulo están disponibles para todos los demás módulos que lo importan. La Guía Oficial de Estilo aconseja que los servicios de toda la aplicación (singletons) que se van a reutilizar en cualquier lugar de la aplicación deben ser proporcionados por algunos Core Module, que se van a importar en el principal App Module para que sea inyectable en todas partes.

Si no utiliza una estructura que implique un módulo Core con singletons compartidos, y está desarrollar independientemente dos NgModules, y desea que un servicio en uno de ellos se utilice en el otro, entonces la única solución es importar el proveedor en el otro :

Aquí está el módulo proveedor:

/// some.module.ts
import { NgModule } from '@angular/core';

import { SomeComponent }   from './some.component';

@NgModule({
    imports: [],
    exports: [],
    declarations: [SomeComponent],
    providers: [ MyService ], // <======================= PROVIDE THE SERVICE
})
export class SomeModule { }

Aquí está el otro módulo, que quiere usar MyService

/// some-other.module.ts
import { NgModule } from '@angular/core';

import { SomeModule } from 'path/to/some.module'; // <=== IMPORT THE JSMODULE

import { SomeOtherComponent }   from './some.other.component';

@NgModule({
    imports: [ SomeModule ], // <======================== IMPORT THE NG MODULE
    exports: [],
    declarations: [SomeOtherComponent],
    providers: [],
})
export class SomeOtherModule { }

De esta manera, el servicio debe ser inyectable en cualquier componente SomeOtherModule declara, y en SomeModule sí mismo-apenas lo pide en el constructor:

/// some-other.module.ts

import { MyService } from 'path/to/some.module/my-service';

/* ...
    rest of the module
*/

export class SomeOtherModule {
    constructor( private _myService: MyService) { <====== INJECT THE SERVICE
        this._myService.dosmth();
    }
}

Si esto no responde a su pregunta, yo te invito a reformularlo.

 42
Author: FacelessPanda,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-11-15 08:32:36
  1. Crear módulo compartido

    @NgModule({}) export class SharedModule { static forRoot(): ModuleWithProviders { return { ngModule: SharedModule, providers: [SingletonService] }; } }

  2. En el módulo de la aplicación son su módulo de aplicación principal importar el módulo compartido como ese

    SharedModule.forRoot()

  3. Cualquiera de los módulos secundarios si necesita importar el módulo compartido, impórtelo sin la raíz para

    SharedModule

Https://angular-2-training-book.rangle.io/handout/modules/shared-modules-di.html

 4
Author: Hager Aly,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-01-15 11:36:19

La respuesta que Günter Zöchbauer dio es genial, sin embargo, un problema que puede tener es que

window.sharedService

Causará un error en TypeScript. Puede evitar esto reemplazando todas las instancias de

window.sharedService

Con

(<any>window).sharedService
 2
Author: Ryan Anderson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-10-20 16:45:04

Intenté usar las ideas en esta respuesta para compartir datos entre múltiples módulos bootstrapeados en mi aplicación angular. Los datos que me interesaban provenían de un http.get () call. Fue una llamada cara y yo quería solamente hacer la llamada una vez y compartir sus resultados entre mis 2 bootstrap módulos.

Inicialmente, almacené el servicio como una propiedad en mi objeto global window como se sugirió, pero al final, decidí usar variables estáticas y llamar a publishReplay () en mi observable para crear un Replaysujeto para reproducir mis emisiones a futuros suscriptores. Esto permitió que varios suscriptores compartieran datos y solo hicieran la llamada REST una vez.

Una advertencia aquí... La pregunta original preguntaba cómo compartir un servicio... Esta respuesta no comparte un servicio... Se crean varios servicios, pero los datos se comparten a medida que el observable se almacena en una variable estática... Eso significa que el observable permanece mientras su aplicación y debido a la llamada a publishReplay() cualquiera que se suscriba a los observables reproduce los datos previamente devueltos.

Aquí está mi código:

import { Injectable } from '@angular/core';
import { Observable, ReplaySubject } from 'rxjs/Rx';
import { Http } from '@angular/http';

@Injectable()
export class InitService {

    static observable: Observable<number> = null;

    constructor(private http: Http) {}

    getInitData(): Observable<number> {
        if (InitService.observable == null) {
            InitService.observable = this.http.get('api/Init')
                .map(this.extractData)
                .publishReplay()
                .refCount()
                .catch(this.handleError);
        }
        return InitService.observable;
    }


    extractData(res: Response) {
        let body: any = res.json();
        return body || {};
    }

}

Espero que esto ayude.

 1
Author: birwin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-06-11 21:00:23