RxJS 系列 – 大杂烩

前言

RxJS 有太多方法了, 想看完整的可以去看 REFERENCE – API List, 这篇介绍一些非 operator 的常用方法.

 

NEVER

NEVER.subscribe({
  complete: () => console.log('complete'), // never be called
  next: () => console.log('next'), // never be called
  error: () => console.log('error'), // never be called
});

就是一个永远不会发布的流...有啥用呢?

比如, 有一个 slide down 的方法, 它支持开关控制

setupSlideDown({
  targetElement: cardWrapper,
  open$: fromEvent(openBtn, 'click'),
  close$: fromEvent(closeBtn, 'click'),
});

所以需要传入 open$ 和 close$ 流. 但是有一个奇葩场景. 这个场景是没有关闭的. 所以就没有 closeBtn click event.

那这时 NEVER 就排上用场了. 

setupSlideDown({
  targetElement: cardWrapper,
  open$: fromEvent(openBtn, 'click'),
  close$: NEVER,
});

 

EMPTY

EMPTY.subscribe({
  complete: () => console.log('complete'), // call immediately
  next: () => console.log('next'), // never be called
  error: () => console.log('error'), // never be called
});

它是一个立马结束的流. 和 NEVER 的是用意图差不多, 都是用在那些特殊场景的.

它也类似我们经常会 用 empty array, empty string, empty function 作为参数或返回. 这样后续就容易统一处理.

 

lastValueFrom & firstValueFrom

lastValueFrom(of(1, 2, 3)).then(value => {
  console.log(value); // 3
});

firstValueFrom(of(1, 2, 3)).then(value => {
  console.log(value); // 1
});

lastValueFrom 是 v7.0 后用来替代以前的 .toPromise 的。

它会监听流的发布,等到流 complete 后,resolve 最后一个 value。

firstValueFrom 同样监听流发布,发布第一个之后它会 unsubscribe 流,然后 resolve first value。

 

finalize

finalize 是一个 operator。它用来监听 Observable 的 "结束" 事件 -- error, complete, unsubscribe

const subject = new Subject();
const obs = subject.asObservable();
const subscription = obs.pipe(finalize(() => console.log('finalize'))).subscribe();

// 下面 3 种情况,finalize 都会接收到
subject.error('error');
subject.complete();
subscription.unsubscribe();

Observable.subscribe 只能监听到 next, error, complete。只有 new Observable 的 callback 函数才可以监听到 unsubscribe。

finalize operator 内部原理是它 wrap 了一层 Observable,unsubscribe 依然是靠 Observable 的 callback 函数监听到的。

 

Conditional add operator into pipe

需求是这样,如果符合某条件,那就添加一个 operator 到 pipe 里头,如果不符合条件就不添加。

function subscribe(delayTime?: number) {
  of(1, 2, 3, 4)
    .pipe(delayTime !== undefined ? delay(delayTime) : obs => obs)
    .subscribe(console.log);
}

subscribe(1000); // with delay
subscribe();     // without delay (同步)

obs => obs 等价于没有 operator。

RxJS 官方给出的 example 也是这样,只是它多了一个 identity 函数

提醒:用 spread operator 会报错哦

of(1, 2, 3, 4)
  // Error: A spread argument must either have a tuple type or be passed to a rest parameter
  .pipe(...(delayTime !== undefined ? [delay(delayTime)] : []))
  .subscribe(console.log);

虽然 runtime 可以跑,但 compile time TypeScript 会报错,这是因为 pipe 的重载方法不支持这个写法。

 

posted @ 2022-10-15 14:55  兴杰  阅读(203)  评论(0编辑  收藏  举报