我在CustomHttp中读过类似访问EventEmitter Service的问题 用户在他的服务中使用EventEmitter,但他在这个评论中被建议 不使用它,而是直接在他的服务中使用Observables。

我也读过这个 问题 解决方案建议将EventEmitter传递给子进程并订阅它。

我的问题是:我是否应该手动订阅EventEmitter?我该如何使用它?


当前回答

从纯实现的角度来看,因为emit和subscribe是EventEmitter公共接口的一部分,所以可以将它们用于实现。

对于angular来说,如果它不想要的话,没有强制从行为中继承,行为可以是EventEmitter类中的私有成员,比如,

public class EventEmitter{
  private _behaviour=new Subject<void>();
  private _behaviour$=this._behaviour.asObservable();
  ......
  public emit(){
    _behaviour.emit();
  }
  ....
}

如果它继承了行为,但行为不像行为,则违反了利斯科夫替换原理。

其他回答

当你想要组件交互时,你需要知道什么是@Input, @Output, EventEmitter和Subjects。

如果组件之间的关系是父子关系,反之亦然,我们使用@input & @output与事件发射器。

@output会触发一个事件,你需要使用事件发射器来触发。

如果不是亲子关系…然后你必须使用主题或通过公共服务

没有:nono和no: yes - yes。 真相在中间 也没有理由因为Angular的下一个版本而害怕。

From a logical point of view, if You have a Component and You want to inform other components that something happens, an event should be fired and this can be done in whatever way You (developer) think it should be done. I don't see the reason why to not use it and i don't see the reason why to use it at all costs. Also the EventEmitter name suggests to me an event happening. I usually use it for important events happening in the Component. I create the Service but create the Service file inside the Component Folder. So my Service file becomes a sort of Event Manager or an Event Interface, so I can figure out at glance to which event I can subscribe on the current component.

我知道,也许我是一个老式的开发者。 但这不是事件驱动开发模式的一部分,这是您特定项目的软件架构决策的一部分。

有些人可能认为直接使用observable很酷。在这种情况下,直接使用可观察对象。 你不是连环杀手干的。除非你是一个精神变态的开发者,到目前为止,这个程序是有效的,去做吧。

从纯实现的角度来看,因为emit和subscribe是EventEmitter公共接口的一部分,所以可以将它们用于实现。

对于angular来说,如果它不想要的话,没有强制从行为中继承,行为可以是EventEmitter类中的私有成员,比如,

public class EventEmitter{
  private _behaviour=new Subject<void>();
  private _behaviour$=this._behaviour.asObservable();
  ......
  public emit(){
    _behaviour.emit();
  }
  ....
}

如果它继承了行为,但行为不像行为,则违反了利斯科夫替换原理。

TL; diana:

不要手动订阅它们,不要在服务中使用它们。按照文档中所示的方式使用它们,只用于在组件中触发事件。不要破坏angular的抽象。

答:

不,您不应该手动订阅它。

EventEmitter是一个angar2抽象,它的唯一目的是在组件中发射事件。引用Rob Wormald的评论

[…EventEmitter实际上是Angular的一个抽象,应该只用于在组件中发射自定义事件。否则,就像使用其他库一样使用Rx。

这在EventEmitter的文档中说得很清楚。

使用by指令和组件来发出自定义事件。

使用它有什么问题?

Angular2永远不会保证EventEmitter将继续是一个可观察对象。因此,这意味着如果代码发生变化,就要重构它。我们必须访问的唯一API是它的emit()方法。我们永远不应该手动订阅EventEmitter。

以上所说的一切在这篇Ward Bell的评论中都更清楚了(建议阅读这篇文章,以及该评论的答案)。引用参考

不要指望EventEmitter继续是一个可观察对象! 不要指望将来会有那些可观察的操作符! 这些将很快被弃用,并可能在发布前删除。 仅在子组件和父组件之间的事件绑定时使用EventEmitter。不要订阅它。不要调用这些方法中的任何一个。只调用eve.emit()

他的评论和罗伯很久以前的评论是一致的。

那么,如何正确使用呢?

只需使用它从组件发出事件。看一下下面的例子。

@Component({
    selector : 'child',
    template : `
        <button (click)="sendNotification()">Notify my parent!</button>
    `
})
class Child {
    @Output() notifyParent: EventEmitter<any> = new EventEmitter();
    sendNotification() {
        this.notifyParent.emit('Some value to send to the parent');
    }
}

@Component({
    selector : 'parent',
    template : `
        <child (notifyParent)="getNotification($event)"></child>
    `
})
class Parent {
    getNotification(evt) {
        // Do something with the notification (evt) sent by the child!
    }
}

如何不使用它?

class MyService {
    @Output() myServiceEvent : EventEmitter<any> = new EventEmitter();
}

就此打住……你已经错了……

希望这两个简单的示例能够阐明EventEmitter的正确用法。

是的,尽管用吧。

EventEmitter是一个在最终的Angular核心API中文档化的公共类型。它是否基于可观察对象无关紧要;如果它记录的emit和subscribe方法适合您的需要,那么就使用它。

正如文件中所述:

使用的处方。可观察对象,但提供了一个适配器,使其按此处指定的方式工作:https://github.com/jhusain/observable-spec 一旦该规范的参考实现可用,就切换到它。

所以他们想要一个类似于Observable的对象,以某种方式表现,他们实现了它,并将其公开。如果它只是一个不应该被使用的Angular内部抽象,他们就不会公开它。

在很多情况下,使用发送特定类型事件的发射器是很有用的。如果这是你的用例,那就去做吧。如果/当他们链接到的规范的参考实现可用时,它应该是一个附带的替代品,就像任何其他填充材料一样。

只要确保传递给subscribe()函数的生成器遵循链接规范。返回的对象保证有一个unsubscribe方法,应该调用该方法来释放对生成器的任何引用(这目前是一个RxJs订阅对象,但这确实是一个不应该依赖的实现细节)。

export class MyServiceEvent {
    message: string;
    eventId: number;
}

export class MyService {
    public onChange: EventEmitter<MyServiceEvent> = new EventEmitter<MyServiceEvent>();

    public doSomething(message: string) {
        // do something, then...
        this.onChange.emit({message: message, eventId: 42});
    }
}

export class MyConsumer {
    private _serviceSubscription;

    constructor(private service: MyService) {
        this._serviceSubscription = this.service.onChange.subscribe({
            next: (event: MyServiceEvent) => {
                console.log(`Received message #${event.eventId}: ${event.message}`);
            }
        })
    }

    public consume() {
        // do some stuff, then later...

        this.cleanup();
    }

    private cleanup() {
        this._serviceSubscription.unsubscribe();
    }
}

所有这些措辞强硬的悲观预测似乎都来自于一个开发者在Angular 2预发布版上的一条Stack Overflow评论。