簡體   English   中英

Angular2:無法訂閱從共享服務發出的自定義事件

[英]Angular2: Cannot subscribe to custom events emitted from shared service

我已經開始學習Angular2,並且在使用發出/訂閱的自定義事件時遇到了麻煩。

我創建了一個小演示來演示: Plunker

如您所見,這里有一個PreviewService類。 此類具有setURL(url:string)方法,如果調用該方法,則將發出contentUrlChange $事件。

SRC /服務/ preview.service.ts

import {Injectable, EventEmitter} from 'angular2/core';

@Injectable()
export class PreviewService {

  private _url: string;

  contentUrlChange$: EventEmitter<any>;

  constructor() {
    this.contentUrlChange$ = new EventEmitter;
  };

  setURL(url: string): void {
    this._url = url;
    this.contentUrlChange$.emit(url);
  };

}

在App組件的構造函數中,我訂閱了PreviewService的contentUrlChange $事件。 如果運行柱塞,則將看到警報窗口。

SRC / app.ts

[...]
constructor(private _previewService: PreviewService) {
  _previewService.contentUrlChange$.subscribe(url => {
    alert("APP " + url);
  })

  _previewService.setURL('http://www.example.com');
};
[...]

但這是我的問題:我有另一個組件PreviewComponent,並且在該組件的構造函數中,就像在App組件的構造函數中一樣,我訂閱了PreviewService的contentUrlChange $事件。 但是奇怪的是,應該出現的警報窗口卻沒有。

SRC /組件/ preview.component.ts

constructor(private _previewService: PreviewService) {
  _previewService.contentUrlChange$.subscribe(url => {
    alert("PREVIEW " + url); // Nothing happens here
  })
};

我通讀了幾個問題/答案,它們表明我正在做的事情應該可以正常工作,但仍然沒有成功。 任何想法/解決方案將不勝感激。 謝謝。

那里的pl子問題很少。 首先,如果將單獨的服務實例注入到組件,則它們將無法訂閱同一事件,僅因為它們將是不同的變量(屬性)。 因此,您必須為每個組件提供相同的服務,只需在應用程序的引導中進行即可:

bootstrap(App, [
  YourService
]).catch(...)

其次,當子組件( PreviewComponent尚未初始化時,您正在從應用程序組件中釋放值。 等待,您可以使用setTimeout(func, 0) (但這是hack,我不建議這樣做),或僅使用內置的angular的OnInit生命周期掛鈎

import {OnInit} from 'angular2/core';

...


ngOnInit() {
  // emit values here
}

這是更新的插件: http : //plnkr.co/edit/okiNPFRKKYXfce1P0D5o

問題在於每個組件都獲得自己的服務實例。

在引導應用程序時,必須將單例服務配置為提供程序。 在您的情況下,這將在main.ts中

import {bootstrap} from 'angular2/platform/browser';
import {App} from './app';
import {PreviewService} from './services/preview.service';

bootstrap(App, [PreviewService]) // configure the PreviewService as a singleton for the entire application.
  .catch(err => console.error(err));

然后,您必須將其刪除為任何特定組件的提供者。

app.ts

import {PreviewService} from './services/preview.service';
import {PreviewComponent} from './components/preview.component';

@Component({
  selector: 'my-app',
  template: `<preview></preview>`,
  directives: [ PreviewComponent ]
})

preview.component.ts

import {Component} from 'angular2/core';
import {PreviewService} from '../services/preview.service';

@Component({
   selector: 'preview',
   template: ``
})

另一件事是, App組件的構造函數將在PreviewComponent的構造函數之前調用。

這意味着,如果您在App構造函數中更改URL,則PreviewComponent尚未訂閱。

我通過對超時進行更改來解決它,我想這在現實生活中會有所不同。

export class App {
  constructor(private _previewService: PreviewService) {
    console.log('app created');
    _previewService.contentUrlChange$.subscribe(url => {
      alert("APP " + url);
    })

    setTimeout(() => {
      alert('setting url');
      _previewService.setURL('http://www.example.com');  
    }, 1000); 

  }
}

您可以在此處看到校正后的松節器。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM