异步数据流的响应式编程库Rxjs(十)- 操作符3

64 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第8天,点击查看活动详情

组合类操作符

combineLatest

组合多个 Observables 来创建一个 Observable ,该 Observable 的值根据每个输入 Observable 的最新值计算得出的。

const { skip,Observable,concatMap, fromEvent, fromPromise, interval, take, from, range, of, map, filter,scan, buffer, Subject, pluck, switchMap, debounceTime, throttleTime, distinct, mergeMap, isEmpty, empty, EMPTY, combineLatest } = require('rxjs');

const source1$ = interval(2000).pipe(take(3));
const source2$ = interval(1000).pipe(take(5));

combineLatest([source1$, source2$]).pipe(map(([s1, s2]) => {
    return `${s1}-${s2},`;
})).subscribe((x) => {
    console.log(x);
});

console.log('End');

End

0-0,

0-1,

0-2,

1-2,

1-3,

1-4,

2-4,

zip

zip操作符是将多个Observable打了个包,第一个Observable中的第一个数据,对应于第二个Observable中第一个数据,第二个数据对应第二个,完全一一对应的,获得的数据是一个数组。日常工作中使用的很多。

const source1$ = interval(2000).pipe(take(3));
const source2$ = interval(1000).pipe(take(5));

zip(source1$, source2$).pipe(map(([s1, s2]) => {
  return `${s1}-${s2},`;
})).subscribe((x) => {
  console.log(x);
});

console.log('End');

End

0-0,

1-1,

2-2,

const age$ = of(27, 25, 29);
const name$ = of('Foo', 'Bar', 'Beer');
const isDev$ = of(true, true, false);

zip(age$, name$, isDev$).pipe(
  map(([age, name, isDev]) => ({ age, name, isDev }))
)
.subscribe(x => console.log(x));

多播类操作符

publish

返回 ConnectableObservable,它是 Observable 的变种,它会一直等待,直到 connnect 方法被调用才会开始把值发送给那些订阅它的观察者。

publish将在V8中彻底废除,可以采用新写法。

const source$ = new Observable((observer) => {
    observer.next(2);
    observer.next(13);
    observer.complete();
});

// const sourceNew$ = source$.pipe(publish());
const sourceNew$ = connectable(source$);

sourceNew$.subscribe((x) => {
    console.log(x);
});

sourceNew$.connect();

console.log('End');

错误处理操作符

catchError

catchError可以优雅地处理observable中的错误,catchError函数中一定要返回一个observable。

const source$ = new Observable((observer) => {
    observer.next(2);
    observer.next(13);
    throw new Error();
    observer.complete();
});

source$.pipe(catchError((err, caught) => {
    return of('出错了');
})).subscribe((x) => {
    console.log(x);
});

console.log('End');

2

13

出错了

End

retry

如果发生错误,以指定次数重试 observable 序列。

const source = interval(1000).pipe(take(20));
const example = source.pipe(
  mergeMap(val => {
    // 抛出错误以进行演示
    if (val > 5) {
      return throwError('Error!');
    }
    return of(val);
  }),
  // 出错的话可以重试2次
  retry(2)
).subscribe((x) => {
    console.log(x);
});

console.log('End');
// 重试两次后结束

工具类操作符

tap

透明地执行操作或副作用,比如打印日志。之前tap操作符叫do。

const source = of(1, 2, 3, 4, 5);
// 使用 tap 透明地打印 source 中的值
const example = source.pipe(
  tap(val => console.log(`BEFORE MAP: ${val}`)),
  map(val => val + 10),
  tap(val => console.log(`AFTER MAP: ${val}`))
);

// 'tap' 并不转换值
// 输出: 11...12...13...14...15
const subscribe = example.subscribe(val => console.log(val));

console.log('End');

BEFORE MAP: 1

AFTER MAP: 11

11

BEFORE MAP: 2

AFTER MAP: 12

12

BEFORE MAP: 3

AFTER MAP: 13

13

BEFORE MAP: 4

AFTER MAP: 14

14

BEFORE MAP: 5

AFTER MAP: 15

15

End

条件和布尔操作符

every

如果完成时所有的值都能通过断言,那么发出 true,否则发出 false 。

// 发出5个值
const source = of(1, 2, 3, 4, 5);
const example = source.pipe(
  // 每个值都是偶数吗?
  every(val => val % 2 === 0)
);
// 输出: false
const subscribe = example.subscribe(val => console.log(val));

console.log('End');

false

End

数学和聚合操作符

count

Counts the number of emissions on the source and emits that number when the source completes.

const numbers = range(1, 7);
const result = numbers.pipe(count(i => i % 2 === 1));
result.subscribe(x => console.log(x));
// Results in:
// 4

reduce

Applies an accumulator function over the source Observable, and returns the accumulated result when the source completes, given an optional seed value.

和数组的reduce方法类似。

const source$ = interval(1000).pipe(take(5));

source$.pipe(reduce((acc, cur) => (acc+cur))).subscribe((x) => {
    console.log(x);
});

console.log('End');

// End
// 10

至此,所有关于操作符的介绍就结束了,操作符是Rxjs的精华,但是没有必要花费大量的精力去精通所有的操作符,先掌握常用的一些操作符就可以,在需要的时候可以再去官网查阅。