rxjs 6 中 concat 和 merge 的区别

Difference between concat and merge in rxjs6

我有 lessons$ observable,它结合了 initialLessons$searchLessons$ observables。

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

当我使用 concat 组合这些 observable 时,只有 initialLessons$ observable 发出并且它似乎根本没有订阅 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();
  });
};

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

这在您的代码中不会发生。 createHttpObservable 创建的 Observable 永远不会完成。它只发出一个 next() 但没有 complete()。所以这就是为什么你正在经历你所描述的。 concat 从未订阅 searchLessons$ 因为 initialLessons$ 从未完成。

因为你已经在调用 .then(data => observer.next(data)) 你也可以添加 complete() 调用。

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