rxjs6中concat和merge之间的区别

时间:2018-12-25 10:46:16

标签: angular rxjs rxjs6

我有lessons$个可观察值,它是由initialLessons$searchLessons$可观察值组成的。

initialLessons$发出页面负载以获取课程列表,并且当用户键入搜索输入时searchLessons$发出以获取过滤后的结果。

当我使用concat组合这些可观察对象时,仅initialLessons$个可观察对象发出,并且似乎根本不订阅searchLessons$。我将其替换为merge,并且效果很好

我只需要知道这种情况的解释!

export class CourseComponent implements OnInit, AfterViewInit {
  @ViewChild('searchInput') input: ElementRef;

  courseId: string = this.route.snapshot.params['id'];

  course$: Observable<Course>;

  lessons$: Observable<Lesson[]>;

  constructor(private route: ActivatedRoute) {}

  ngOnInit() {
    this.course$ = createHttpObservable(`/api/courses/${this.courseId}`);
  }

  ngAfterViewInit() {
    const initialLessons$: Observable<Lesson[]> = this.loadLessons();

    const searchLessons$: Observable<Lesson[]> = fromEvent<any>(
      this.input.nativeElement,
      'keyup'
    ).pipe(
      debounceTime(400),
      map(event => event.target.value),
      distinctUntilChanged(),
      switchMap(search => this.loadLessons(search))
    );

    this.lessons$ = merge(initialLessons$, searchLessons$);
  }

  loadLessons(search = ''): Observable<Lesson[]> {
    return createHttpObservable(`/api/lessons?courseId=${this.courseId}&pageSize=100&filter=${search}`
).pipe(map(res => res['payload']));

} }

修改:

这是createHttpObservable代码:

import { Observable } from 'rxjs';

export const createHttpObservable = (url: string) => {
  return Observable.create(observer => {
    const controller = new AbortController();
    const signal = controller.signal;

    fetch(url, { signal })
      .then(res => res.json())
      .then(data => observer.next(data))
      .catch(err => console.error(err));

    return () => controller.abort();
  });
};

1 个答案:

答案 0 :(得分:1)

concat仅在上一个Observable完成时订阅下一个源Observable。

这就是您的代码中没有发生的事情。由createHttpObservable创建的Observable永远不会完成。它仅发出一个next(),但不发出complete()。这就是为什么您要体验自己的描述。 concat从未订阅过searchLessons$,因为initialLessons$从未完成。

由于您已经在呼叫.then(data => observer.next(data)),因此也可以在此添加complete()呼叫。

.then(data => {
  observer.next(data);
  observer.complete();
})