Как обмениваться услугами между двумя модулями - @NgModule в angular не между компонентами?
В моем приложении у меня есть два разных модуля начальной загрузки (@NgModule
), работающих независимо в одном приложении. Не существует одного отдельного модуля начальной загрузки приложения angular, и теперь я хочу, чтобы они обменивались данными друг с другом и обменивались данными.
Я знаю через службу @Injectable
как поставщик в модуле, я могу обмениваться данными во всем компоненте в @NgModule
, но как я буду обмениваться данными между двумя разными модулями (не входящими в состав модуля).
Можно ли получить доступ к одному объекту службы в другом модуле? Есть ли способ получить доступ к объекту службы, доступному в памяти браузера, и использовать его в моем другом модуле angular?
Ответы
Ответ 1
Вы можете создать экземпляр службы вне 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
}));
}
}
См. также Как динамически создавать загрузочные модалы в качестве Angular2 компонентов?
Ответ 2
В соответствии с окончательной версией Angular 2 услуги, предоставляемые модулем, доступны для каждого другого модуля, который его импортирует.
Руководство по официальному стилю сообщают, что службы (одноадресные) в рамках всей программы, которые должны использоваться повторно в любом месте приложение должно быть предоставлено некоторым Core Module
, которое должно быть импортировано в основной App Module
, поэтому оно будет внедряться повсеместно.
Если вы не используете структуру, которая включает в себя основной модуль с общими синглонами, и вы самостоятельно разрабатываете два NgModules, и хотите, чтобы одна из них использовалась в другом, то единственным решением является импорт провайдер в другой:
Здесь модуль провайдера:
/// 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
declares, а в 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();
}
}
Если это не ответит на ваш вопрос, я предлагаю вам переформулировать его.
Ответ 3
Это лучший способ добиться обмена службами между модулями
fooobar.com/questions/229920/...
Ответ 4
Ответ, который дал Günter Zöchbauer, велик, однако, один вопрос, который у вас может быть, заключается в том, что
window.sharedService
приведет к ошибке в TypeScript. Вы можете обойти это, заменив все экземпляры
window.sharedService
с
(<any>window).sharedService
Ответ 5
Я попытался использовать идеи в этом ответе для обмена данными между несколькими загрузочными модулями в моем приложении angular. Данные, которые меня интересовали, исходили из обращения http.get(). Это был дорогой звонок, и я хотел только сделать звонок один раз и поделиться своими результатами между моими 2 загруженными модулями.
Вначале я сохранил службу как свойство в моем глобальном объекте окна, как было предложено, но в конце я решил использовать статические переменные и вызывать publishReplay() на моем наблюдаемом, чтобы создать ReplaySubject, чтобы воспроизвести мои выбросы будущим подписчикам, Это позволило нескольким подписчикам обмениваться данными и только один раз сделать звонок REST.
Одно предостережение здесь... Первоначальный вопрос задал вопрос о том, как разделить одну услугу... Этот ответ не использует одну услугу... Создано несколько сервисов, но данные разделяются, поскольку наблюдаемый хранится в статической переменной... Это означает, что наблюдаемые палочки до тех пор, пока ваше приложение и из-за вызова publishReplay()
любой, кто подписывается на наблюдаемый, повторяет ранее возвращенные данные.
Вот мой код:
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 || {};
}
}
Надеюсь, что это поможет.
Ответ 6
-
создать общий модуль
@NgModule({})
export class SharedModule {
static forRoot(): ModuleWithProviders {
return {
ngModule: SharedModule,
providers: [SingletonService]
};
}
}
-
в модуле приложения - ваш родительский модуль приложения импортирует совместно используемый модуль
SharedModule.forRoot()
-
любые дочерние модули, если вам нужно импортировать совместно используемый модуль, импортируйте его без root для
SharedModule
https://angular-2-training-book.rangle.io/handout/modules/shared-modules-di.html