web-dev-qa-db-fra.com

Comment partager le service entre deux modules - @NgModule in angular pas entre les composants?)

Dans mon application, j'ai deux bootstrap module (@NgModule) fonctionnant indépendamment dans une application. Il n'y a pas un seul angular app séparé bootstrap et maintenant je veux qu'ils puissent communiquer entre eux et partager des données).

Je sais par @Injectable service en tant que fournisseur du module, je peux partager des données dans tous les composants sous @NgModule mais comment je vais partager des données entre deux modules différents (pas de composant à l'intérieur du module).

Existe-t-il un moyen d'accéder à un objet de service dans un autre module? Existe-t-il un moyen d'accéder à l'objet de service disponible dans la mémoire du navigateur et de l'utiliser dans mon autre module angular?

35
Aniruddha Das

Vous pouvez instancier un service en dehors de Angular et donner une valeur:

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 une application modifie l'état dans SharedService ou appelle une méthode qui provoque l'émission d'une valeur par un Observable et que l'abonné est dans une application différente de celle de l'émetteur, le code de l'abonné est exécuté dans le NgZone de l'émetteur.

Par conséquent, lorsque vous vous abonnez à un observable dans SharedService, utilisez

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

Voir aussi Comment créer dynamiquement bootstrap modals en tant que composants Angular2? )

8
Günter Zöchbauer

Selon la version finale de Angular 2, les services fournis par un module sont disponibles pour tous les modules qui l’importent. Le Guide de la forme officiel indique que des services à l’échelle de l’application (singletons) qui doivent être réutilisés n'importe où dans l'application doivent être fournis par un Core Module, à importer dans le principal App Module donc ce serait injectable partout.

Si vous n'utilisez pas une structure impliquant un module central avec des singletons partagés, et que vous développez indépendamment deux modules NgModules et que vous souhaitez qu'un service de l'un d'eux soit utilisé dans l'autre, la seule solution consiste à importer le fournisseur dans L'autre :

Voici le module fournisseur:

/// 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 { }

Voici l'autre module, qui veut utiliser 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 cette façon, le service devrait être injectable dans n'importe quel composant SomeOtherModule déclare, et dans SomeModule lui-même - il suffit de le demander dans le constructeur:

/// 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 cela ne répond pas à votre question, je vous invite à la reformuler.

47
FacelessPanda
  1. créer un module partagé

    @NgModule({})
    export class SharedModule {
        static forRoot(): ModuleWithProviders {
            return {
                ngModule: SharedModule,
                providers: [SingletonService]
            };
        }
    }
    
  2. dans le module d'application sont votre module d'application parent importer le module partagé comme ça

    SharedModule.forRoot()
    
  3. tous les modules enfants si vous devez importer le module partagé, importez-le sans le pour root

    SharedModule
    

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

14
Hager Aly

J'ai essayé d'utiliser les idées de cette réponse pour partager des données entre plusieurs modules amorcés dans mon angular application. Les données qui m'intéressaient provenaient d'un appel http.get (). Il s'agissait d'un appel coûteux et je voulais faire l'appel qu'une seule fois et partager ses résultats entre mes 2 modules bootstrapped.

Initialement, j'ai stocké le service en tant que propriété sur mon objet de fenêtre globale, comme suggéré, mais j'ai finalement décidé d'utiliser des variables statiques et d'appeler publishReplay () sur mon observable pour créer un ReplaySubject afin de relire mes émissions aux futurs abonnés. Cela permettait à plusieurs abonnés de partager des données et de ne lancer l'appel qu'une seule fois REST).

Une mise en garde ici ... La question initiale demandait comment partager un service ... Cette réponse ne partage pas un service ... Plusieurs services sont créés, mais les données sont partagées car l'observable est stocké dans une variable statique ... Cela signifie que l'observable reste aussi longtemps que votre application et en raison de l'appel à publishReplay() toute personne qui s'abonne à l'observable relit les données précédemment renvoyées.

Voici mon code:

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 || {};
    }

}

J'espère que cela t'aides.

1
birwin

La réponse donnée par Günter Zöchbauer est excellente, mais vous avez peut-être un problème:

window.sharedService

provoquera une erreur dans TypeScript. Vous pouvez contourner ce problème en remplaçant toutes les instances de

window.sharedService

avec

(<any>window).sharedService
1
Ryan Anderson