繁体   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