ngOnInit()中的RxJS可观察生命周期

时间:2019-03-13 14:59:45

标签: typescript

ngOnInit(): void {
    // convert the `keyup` event into an observable stream
    Observable.fromEvent(this.el.nativeElement, 'keyup')
      .map((e: any) => e.target.value) // extract the value of the input
      .filter((text: string) => text.length > 1) // filter out if empty
      .debounceTime(250)                         // only once every 250ms
      .do(() => this.loading.emit(true))         // enable loading
      // search, discarding old events if new input comes in
      .map((query: string) => this.youtube.search(query))
      .switch()
      // act on the return of the search
      .subscribe(
        (results: SearchResult[]) => { // on sucesss
          this.loading.emit(false);
          this.results.emit(results);
        },
        (err: any) => { // on error
          console.log(err);
          this.loading.emit(false);
        },
        () => { // on completion
          this.loading.emit(false);
        }
      );
  }

据我所知,第一次检测更改后便调用ngOnInit()。我的问题是Observable.fromEvent创建一个Observable流。这是否意味着在触发“ keyup”事件时使用相同的流?如果是这样,map()实际上会迭代该流中的每个值?我先输入a然后输入b,所以流中有2个值?一个是另一个是a,b?这就是为什么使用switch方法仅返回最新值的原因?

2 个答案:

答案 0 :(得分:2)

  

据我所知,第一次检测更改后便调用ngOnInit()。

首次收到输入属性。这是从父组件中的更改检测周期开始的。

  

我的问题是Observable.fromEvent创建一个Observable流。这是否意味着在触发“ keyup”事件时使用相同的流?如果是这样,map()实际上会迭代该流中的每个值?我先输入a然后输入b,所以流中有2个值?一个是另一个是a,b?

是的,所有keyup事件都依次流传输到该单个可观察事件。

  

这就是为什么使用switch方法仅返回最新值的原因?

流式传输新值后,switch用于取消示例代码中对youtube.search(query)的所有未决调用。

Observable.fromEvent(this.el.nativeElement, 'keyup')

我不喜欢这种方法,因为this.el当时可能不可用,或者可以在组件的生命周期中重新创建。通过这种方法,您可以从创建的第一个元素中获取事件,这些事件可能会起作用,然后突然停止工作。

相反,我将模板上的keyup事件和next()绑定到主题。

<input type="text" (keyup)="onKeyup($event)">
import {Subject} from 'rxjs';
...
keyupSubject = new Subject();
endEvent = new Subject();

ngOnInit(): void {
    this.keyupSubject
        .map()
        .filter()
        .debounceTime()
        .takeUntil(this.endEvent) // automatically unsubscribe when component is destroyed
        .subscribe(() => {
            ...
        });        
}

ngOnDestroy() {
    this.endEvent.next();
}

onKeyup(event) {
    this.keyupSubject.next(event);
}

答案 1 :(得分:0)

调用component时,仅调用一次

ngOnInit()一次。

每次角度检测到变化时都会调用

ngOnChange()。

尝试使用ngOnChange()而不是ngOnInit()