问题
In my application, I have two different bootstrap module (@NgModule
) running independently in one application. There are not one angular app bit separate bootstrap module and now I want they should communicate to each other and share data.
I know through @Injectable
service as the provider in the module, I can share data in all component under @NgModule
but how I will share data between two different module ( not component inside module ).
Is there a way one service object can be accessed in another module? Is there a way I can access the object of Service available in browser memory and use it in my other angular module?
回答1:
You can instantiate a service outside Angular and provide a value:
class SharedService {
...
}
window.sharedService = new SharedService();
@NgModule({
providers: [{provide: SharedService, useValue: window.sharedService}],
...
})
class AppModule1 {}
@NgModule({
providers: [{provide: SharedService, useValue: window.sharedService}],
...
})
class AppModule2 {}
If one application change the state in SharedService
or calls a method that causes an Observable
to emit a value and the subscriber is in a different application than the emitter, the code in the subscriber is executed in the NgZone
of the emitter.
Therefore when subscribing to an observable in SharedService
use
class MyComponent {
constructor(private zone:NgZone, private sharedService:SharedService) {
sharedService.someObservable.subscribe(data => this.zone.run(() => {
// event handler code here
}));
}
}
See also How to dynamically create bootstrap modals as Angular2 components?
回答2:
As per the final version of Angular 2, services provided by a module are available to every other module that imports it.
The Official Style Guide advice that application-wide services (singletons) that are to be reused anywhere in the application should be provided by some Core Module
, that is to be imported in the main App Module
so it would be injectable everywhere.
If you do not use a structure that involves a Core Module with shared singletons, and you are independently developing two NgModules, and you want a service in one of them to be used in the other, then the only solution is to import the provider into the other :
Here's the provider module:
/// 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 { }
Here's the other module, that wants to use 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 { }
This way, the service should be injectable in any component SomeOtherModule
declares, and in SomeModule itself - just ask for it in the 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();
}
}
If this doesn't answer your question, I invite you to re-formulate it.
回答3:
create shared module
@NgModule({}) export class SharedModule { static forRoot(): ModuleWithProviders { return { ngModule: SharedModule, providers: [SingletonService] }; } }
in the app module are your parent app module import the shared module like that
SharedModule.forRoot()
any the children modules if you need to import the shared module import it without the for root
SharedModule
https://angular-2-training-book.rangle.io/handout/modules/shared-modules-di.html
回答4:
The answer that Günter Zöchbauer gave is great, however, one issue you may have is that
window.sharedService
will cause an error in TypeScript. You can get around this by replacing all instances of
window.sharedService
with
(<any>window).sharedService
回答5:
I attempted to use the ideas in this answer to share data between multiple bootstrapped modules in my angular application. The data I was interested in was coming from an http.get() call. It was an expensive call and I wanted to only make the call once and share its results between my 2 bootstrapped modules.
Initially, I stored the service as a property on my global window object as suggested, but in the end, I decided to use static variables and call publishReplay() on my observable to create a ReplaySubject to replay my emissions to future subscribers. This allowed multiple subscribers to share data and only make the REST call once.
One caveat here... The original question asked how to share one service... This answer does not share one service... Multiple services are created, but the data is shared as the observable is stored in a static variable... That means the observable sticks around as long as your application and because of the call to publishReplay()
anyone who subscribes to the observable replays the data previously returned.
Here is my 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 || {};
}
}
Hope this helps.
回答6:
I think below is a neat and clean solution. I used in many projects.
Create a shared module (AdModule
in my case)
/// ad.module.ts
import ...
// create shared service(AdmobService in my case) object, pass constructor params (if you required)
const admobService = new AdmobService(new AdMobFree(), new InAppPurchase());
@NgModule({
providers: [
...,
{ provide: AdmobService, useValue: admobService }, // use shared service here like this
]
})
export class AdModule { }
import AdModule
in any module where you want to use shared service (AdmobService
)
Module1
/// module1.ts
@NgModule({
imports: [
...,
AdModule, // import shared module
],
})
export class Module1 { }
Module 2
/// module2.ts
@NgModule({
imports: [
...,
AdModule, // import shared module
],
})
export class Module2 { }
来源:https://stackoverflow.com/questions/40089316/how-to-share-service-between-two-modules-ngmodule-in-angular-not-between-to-c