Подтвердить что ты не робот

Как обмениваться услугами между двумя модулями - @NgModule в angular не между компонентами?

В моем приложении у меня есть два разных модуля начальной загрузки (@NgModule), работающих независимо в одном приложении. Не существует одного отдельного модуля начальной загрузки приложения angular, и теперь я хочу, чтобы они обменивались данными друг с другом и обменивались данными.

Я знаю через службу @Injectable как поставщик в модуле, я могу обмениваться данными во всем компоненте в @NgModule, но как я буду обмениваться данными между двумя разными модулями (не входящими в состав модуля).

Можно ли получить доступ к одному объекту службы в другом модуле? Есть ли способ получить доступ к объекту службы, доступному в памяти браузера, и использовать его в моем другом модуле angular?

4b9b3361

Ответ 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();
    }
}

Если это не ответит на ваш вопрос, я предлагаю вам переформулировать его.

Ответ 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