rxjs基础

创建一个用于处理网络请求的observable

  1. import { noop, Observable } from "rxjs";
  2. // 创建一个可以用于fetch指定数据的observable
  3. const http$ = new Observable((observer) => {
  4. fetch("/api/courses")
  5. .then((response) => response.json())
  6. .then((body) => {
  7. // 由于是冷的observable 只能next一次 同时complete应该发生在next之后
  8. observer.next(body);
  9. observer.complete();
  10. })
  11. .catch((err) => {
  12. observer.error(err);
  13. });
  14. });
  15. http$.subscribe(
  16. (data) => {
  17. console.log({ data });
  18. },
  19. noop,
  20. () => {
  21. console.log("complete");
  22. }
  23. );

rxjs算子

几种不同的map

  1. this.form.valueChanges
  2. .pipe(
  3. filter(() => this.form.valid),
  4. distinctUntilChanged(),
  5. // concatMap在一个请求结束后执行下一个 瀑布流为顺序邻接
  6. // concatMap((changes) => this.saveCourse(changes))
  7. // 不会等上一个结束 瀑布流会有交叉
  8. mergeMap((changes) => this.saveCourse(changes))
  9. )
  10. .subscribe((res) => {});
  11. fromEvent(this.saveButton.nativeElement, "click")
  12. // 当当前请求结束时 才会允许触发下一次请求 有点类似于throttle 用于防止按钮多次被按
  13. .pipe(exhaustMap((changes) => this.saveCourse(this.form.value)))
  14. .subscribe();

总结下,

concatMap

concatMap可以用于进行Observable的顺序连接,当一个ob发射结束后另一个ob发射,
image.png
image.png
它的事件瀑布流时顺序的,当一个时间执行结束后可以执行下一个事件。
可以想象到的一个使用场景是,定义一个初始化和初始化后继续执行的代码的同一性场景:
image.png

mergeMap

image.png
image.png
事件流交叉

switchMap

image.png
switch会取消之前的请求
image.png

exhaustMap

image.png
当前请求结束后才可以触发下一次请求
使用场景,按钮在点击后再次点击无效

shareReplay

将一个Ob置为热的,使它只会触发一次,见下面代码:

  1. ngOnInit() {
  2. // 创建一个可以用于fetch指定数据的observable
  3. const http$: Observable<CoursePayload> = createHttpObservable(
  4. "/api/courses"
  5. ) as Observable<CoursePayload>;
  6. const courses$ = http$.pipe(
  7. map((res) => Object.values(res.payload)),
  8. // 变流为多播 只会触发一次
  9. shareReplay()
  10. );
  11. this.beginnerCourse$ = courses$.pipe(
  12. map((courses) => {
  13. return courses.filter((course) => course.category === "BEGINNER");
  14. })
  15. );
  16. this.advancedCourse$ = courses$.pipe(
  17. map((courses) => {
  18. return courses.filter((course) => course.category === "ADVANCED");
  19. })
  20. );
  21. }

如果没有shareReplay,http请求会触发两次。