如何在两个模块之间共享服务 - @NgModule在角度之间而不是在组件之间?

问题描述 投票:34回答:5

在我的应用程序中,我有两个不同的bootstrap模块(@NgModule)在一个应用程序中独立运行。没有一个角度app位单独的bootstrap模块,现在我希望他们应该相互通信并共享数据。

我知道通过@Injectable服务作为模块中的提供者,我可以在@NgModule下的所有组件中共享数据但是我将如何在两个不同的模块之间共享数据(不是模块内部的组件)。

有没有办法在另一个模块中访问一个服务对象?有没有办法可以访问浏览器内存中可用的服务对象并在我的其他角度模块中使用它?

angular angular2-services angular2-modules
5个回答
8
投票

您可以在Angular之外实例化一个服务并提供一个值:

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

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

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

如果一个应用程序更改SharedService中的状态或调用导致Observable发出值的方法,并且订阅者与发射器位于不同的应用程序中,则订阅者中的代码将在发射器的NgZone中执行。

因此,当订阅SharedService中的观察者时使用

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

另见How to dynamically create bootstrap modals as Angular2 components?


47
投票

根据Angular 2的最终版本,模块提供的服务可用于导入它的每个其他模块。 Official Style Guide建议在应用程序的任何地方重复使用的应用程序范围的服务(单例)应该由一些Core Module提供,即在主要的App Module中导入,因此它可以在任何地方注入。

如果您不使用涉及具有共享单例的核心模块的结构,并且您要独立开发两个NgModule,并且您希望其中一个服务在另一个中使用,那么唯一的解决方案是将提供程序导入另一个 :

这是提供者模块:

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

这是另一个想要使用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 { }

这样,服务应该可以注入任何组件SomeOtherModule声明,并在SomeModule本身 - 只需在构造函数中请求它:

/// 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();
    }
}

如果这不能回答你的问题,我邀请你重新制定它。


14
投票
  1. 创建共享模块 @NgModule({}) export class SharedModule { static forRoot(): ModuleWithProviders { return { ngModule: SharedModule, providers: [SingletonService] }; } }
  2. 在app模块中,您的父app模块会像这样导入共享模块 SharedModule.forRoot()
  3. 任何子模块如果你需要导入共享模块导入它而不用for root SharedModule

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


1
投票

GünterZöchbauer给出的答案很棒,但是,你可能遇到的一个问题是

window.sharedService

将在TypeScript中导致错误。您可以通过替换所有实例来解决这个问题

window.sharedService

(<any>window).sharedService

1
投票

我尝试使用此答案中的想法在我的角度应用程序中的多个引导模块之间共享数据。我感兴趣的数据来自http.get()调用。这是一个昂贵的电话,我只想拨打一次电话,并在我的2个自举模块之间分享它的结果。

最初,我按照建议将服务存储为我的全局窗口对象上的属性,但最后,我决定使用静态变量并在我的observable上调用publishReplay()来创建一个ReplaySubject,以便将我的排放重放给未来的订阅者。这允许多个订阅者共享数据并仅进行一次REST调用。

这里有一点需要注意......最初的问题是如何共享一个服务......这个答案不共享一个服务...创建了多个服务,但是当observable存储在一个静态变量中时,数据被共享...这意味着只要您的应用程序和观察到publishReplay()的任何人订阅了observable的任何人都会重复之前返回的数据,那么observable会一直存在。

这是我的代码:

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

}

希望这可以帮助。

© www.soinside.com 2019 - 2024. All rights reserved.