Observable可观察序列中,我们可以使用操作符来对流进行处理,以实现我们想要的结果。详细的操作符以及具体使用可参考文档:https://rxjs-cn.github.io/learn-rxjs-operators/operators/utility/do.html
常见的操作符如下:
合并相关操作符:
【1】concat N个请求按顺序串行发出(前一个结束再发下一个)
Observable.concat(...obs).subscribe(detail => console.log('最后一个请求触发的回调'));
【2】merge N个请求同时并行发出,对于每一个到达就触发一次回调
Observable.merge(...obs).subscribe(detail => console.log('每个请求都触发回调'));
【3】forkJoin N个请求同时发出并且要求全部到达后合并为数组,触发一次回调
Observable.forkJoin(...obs).subscribe(detailArray => console.log('触发一次回调'));
【4】 race N个请求按时间依次发出,使用最先发出值的 observable
// 接收第一个发出值的 observable
const example = race(
// 每1.5秒发出值
interval(1500),
// 每1秒发出值
interval(1000).pipe(mapTo('1s won!')),
// 每2秒发出值
interval(2000),
// 每2.5秒发出值
interval(2500)
);
// 输出: "1s won!"..."1s won!"...etc
const subscribe = example.subscribe(val => console.log(val));
【5】startWith 以给定的某个值开始发送请求
// RxJS v6+
import { startWith } from 'rxjs/operators';
import { interval } from 'rxjs';
// 每1秒发出值
const source = interval(1000);
// 以 -3, -2, -1 开始
const example = source.pipe(startWith(-3, -2, -1));
// 输出: -3, -2, -1, 0, 1, 2....
const subscribe = example.subscribe(val => console.log(val));
【6】zip 当一个observable完成时,便不会再发出更多的值
// RxJS v6+
import { take } from 'rxjs/operators';
import { interval, zip } from 'rxjs';
// 每1秒发出值
const source = interval(1000);
// 当一个 observable 完成时,便不会再发出更多的值了
const example = zip(source, source.pipe(take(2)));
// 输出: [0,0]...[1,1]
const subscribe = example.subscribe(val => console.log(val));
转换相关操作符:
【1】map 对observable中的每个值进行映射
// RxJS v6+
import { from } from 'rxjs';
import { map } from 'rxjs/operators';
// 发出 (1,2,3,4,5)
const source = from([1, 2, 3, 4, 5]);
// 每个数字加10
const example = source.pipe(map(val => val + 10));
// 输出: 11,12,13,14,15
const subscribe = example.subscribe(val => console.log(val));
【2】switchMap 每次发出时,会取消前一个 observable 的订阅,然后订阅一个新的 observable
this.ms.getLoan(data)
.pipe(
finalize(() => (this.isLoading = false)),
filter(loan => !!loan),
tap(loan => (this.loan = loan)),
take(1),
switchMap(loan => metisService.repaymentsUpdate(loan!.id)),
map(list =>
list.sort((updateA, updateB) => +updateB.updateDate - +updateA.updateDate)
),
switchMap(list => {
if (list && list.length) {
const updateTime = moment(list[0].updateDate).format(API_DATE_FORMAT);
return this.ms.repaymentsUpdateByLoanId(this.loan!.id, updateTime);
} else {
return of(null);
}
})
)
.subscribe(list => (this.loanRepayments = list));
//最终的subscribe拿到的是最后依次switchMap里面的值
【3】concatMap 前一个observable 中的值映射完成后才会订阅下一个
// RxJS v6+
import { of } from 'rxjs';
import { concatMap, delay, mergeMap } from 'rxjs/operators';
// 发出延迟值
const source = of(2000, 1000);
// 将内部 observable 映射成 source,当前一个完成时发出结果并订阅下一个
const example = source.pipe(
concatMap(val => of(`Delayed by: ${val}ms`).pipe(delay(val)))
);
// 输出: With concatMap: Delayed by: 2000ms, With concatMap: Delayed by: 1000ms
const subscribe = example.subscribe(val =>
console.log(`With concatMap: ${val}`)
);
工具类操作符:
【1】do 或者 tap 用于窃听Observable中的值,一般用于做调试
this.heraService
.getLoanHistory(this.customerId)
.pipe(
tap(() => (this.isLoading = false)),
tap(data => (this.creditHistory = data))
)
.subscribe(data => this.renderCreditChart(data));
创建相关操作符:
【1】interval 给定时间间隔发出
interval(200)
.pipe(
filter(() => !!this.searchForm),
take(1)
)
.subscribe(() => {
this.gridService.refresh();
});
过滤相关操作符:
【1】filter 根据指定条件过滤出符合条件的
// RxJS v6+
import { from } from 'rxjs';
import { filter } from 'rxjs/operators';
// 发出 (1,2,3,4,5)
const source = from([1, 2, 3, 4, 5]);
// 过滤掉奇数
const example = source.pipe(filter(num => num % 2 === 0));
// 输出: "Even number: 2", "Even number: 4"
const subscribe = example.subscribe(val => console.log(`Even number: ${val}`));