前言

前几篇介绍过了

Creation Operators

Filtering Operators

Join Creation Operators

Error Handling Operators

Transformation Operators

Join Operators

这篇继续介绍 Utility Operators

参考

Docs – Utility Operators

tap

tap 是用来写 side effect 的. RxJS 也带有函数式的概念.

一个 Observable 流是没有任何 side effect 的. 如果想搞 side effect 就可以利用 tap operator

from([1, 2, 3])
.pipe(tap(v => console.log('tap: ' + v)))
.subscribe();

效果

tap 不需要返回任何值, upstream 的 value 会自动被传到 downstream. tap 只负责 side effect 就可以了.

delay

顾名思义, 就是延后一个时间才接收.

console.log('start');
from([1, 2, 3])
.pipe(delay(1000))
.subscribe(v => console.log(v));
console.log('end');

下面左图是没有 delay 的效果, 它是同步的, 右图是有 delay 的效果, start end 是同步, 1 秒后 1,2,3 才接收.

你可能好奇为什么不是

1 > delay 1 秒 > 2 > delay 1 秒 > 3

而是

delay 1 秒 1,2,3

关于这点, 可以回看 RxJS 系列 – Scheduler 里面有解释到. 这里不展开了.

delayWhen

delayWhen 是 delay 的底层实现. 下面是 delay 的源码. 里面调用了 delayWhen

delayWhen 接收一个方法, 参数是源 source 发布的值, 返回一个 Observable. 这个 Observable 发布表示 delay 结束.

from([1, 2, 3])
.pipe(delayWhen(v => timer(v * 1000)))
.subscribe(v => console.log(v));

第一个进入 delayWhen 的值是 1. 于是 timer(1 * 1000), 然后 1 秒后发布.

第二个进入的值是 2, timer(2 * 1000) 2 秒后发布

3 就是三秒后发布

最终效果

dematerialize

dematerialize 可以让我们通过 next 的方式输出 next, error, complete 的效果.

例子说明

首先我们有个 Subject. 它发布 ObservableNotification. 这个是 RxJS 的一个特别 interface

const subject = new Subject<ObservableNotification<string>>();

发布长这样

subject.next({ kind: 'N', value: 'next value' });
subject.next({ kind: 'E', error: 'error value' });
subject.next({ kind: 'C' });

kind: 'N' | 'E' | 'C' 分别代表 Next, Error, Complete

接收长这样

subject.pipe(dematerialize()).subscribe({
next: v => console.log('next', v),
complete: () => console.log('complete'),
error: e => console.log('error', e),
});

当发布 kind: 'E', subscribe 就会接收到 error.

当然如果直接调用 subject.complete 或 subject.error, subscribe 依然会收到 complete 和 error, dematerialize 只是扩展了 next 的表达, 并没有破坏任何原本的东西.

materialize

dematerialize 是让 next 变得可以发布 error, complete

materialize 则是把 .complete, .error 变成 next 发布

在 materialize 的情况下, subscribe 永远只需要处理 next, 因为永远都接收不到 complete 和 error

const subject = new Subject<string>();

subject.pipe(materialize()).subscribe({
next: v => console.log(v),
complete: () => console.log('complete'), // never be called
error: e => console.log('error', e), // never be called
}); subject.next('value'); // console: { kind: 'N', value: 'value', error: undefined, hasValue: true }
subject.error('error'); // console: { kind: 'E', value: undefined, error: 'error', hasValue: false }

observeOn, subscribeOn

回看 RxJS 系列 – Scheduler, 里面已经介绍过了.

简单说

subscribeOn 是 delay subscribe, 但没有 delay 后续的发布 (放在 pipe 任何位置效果一样)

observeOn 是 delay 后续的发布, 但是没有 delay 源头 (放在 pipe 的位置不同效果不同)

schedule([1,2,3], asyncScheduler) 是源头开始 delay 发布.

3 种方式表示了不同阶段的 delay

schedule 源头 > observeOn 中间 > subscribeOn 结尾

timeInterval

timeInterval 能让我们知道每一次发布距离上一次间隔了多久.

const subject = new Subject<string>();

subject.pipe(timeInterval()).subscribe(({ value, interval }) => console.log([value, interval]));

(async () => {
await delayAsync(2000);
subject.next('first'); await delayAsync(4000);
subject.next('second');
})();

效果

最终接收的 value 被 wrap 了一层对象. 里面包含了间隔时间和原本的值.

第一个 2 秒的间隔是从 subscribe() 开始到第一次的 next 发布. 2005 多了 5ms 是正常的, JS 单线程总是会有微差的.

第二个 4 秒就是从第一次发布到第二次发布的间隔时间.

timestamp

timestamp 和 timeInterval 类似. 只是它返回的不是间隔的 ms. 而是 Epoch Time.

subject.pipe(timestamp()).subscribe(({ value, timestamp }) => console.log([value, timestamp]));

效果

timeout

timeout 的概念就是限定一个时间内, 必须完成任务, 没有完成就一个特殊处理.

用在 RxJS 指的是一个 stream 必须在 timeout 限制的时间内, 完成发布. 没有发布就 failure, 然后就一个特殊处理.

const subject = new Subject<string>();
subject
.pipe(
timeout({
each: 2000,
})
)
.subscribe({
next: () => console.log('next'),
error: e => console.log('error', e),
complete: () => console.log('complete'),
});

上面的 timeout 要求 subject 从 subscribe() 开始, 每一次发布间隔都不可以超出 2 秒

(async () => {
await delayAsync(1000);
subject.next('ok1'); // 可以
await delayAsync(1500);
subject.next('ok2'); // 可以
await delayAsync(2500); // timeout error, 从上一次发布已经超过了要求的 2 秒
subject.next('ok3');
})();

效果

一旦超过时间, 就会触发 error

first

把 each 改成 first, 就变成只限制第一次的发布必须在时间内.

timeout({
first: 2000,
})

效果

没有 error 了, 因为第一次发布在限定的 2 秒就 ok 了

Date

first 还支持绝对时间

timeout({
first: new Date(2023, 1, 1),
})

只要在 01-01-2023 前发布就 ok, 超过这个时间就报错.

custom error handle

如果不希望 throw error, 我们可以自己设定处理方式

timeout({
first: 1000,
with: info => {
console.log(info);
return EMPTY;
},
})

效果

通过 with 返回一个 Observable, downstream 会 subscribe 它. 上面例子我返回 EMPTY, 所以就进入了 subscribe 的 complete.

shorthand

timeout(1000)
// 相等于
timeout({ each: 1000 }) timeout(new Date())
// 相等于
timeout({ first: new Date() })

toArray

toArray 有点像 buffer, 但是它比较简单明了.

当 Observable 还没有 complete 前, 所以发布的值会被保存起来, 不会接收.

一直到 Observable complete 以后, subscrube 会一次性接收到所有之前保存的值. 以 array 的方式接收.

const subject = new Subject<number>();
subject.pipe(toArray()).subscribe(v => console.log(v));
subject.next(1);
subject.next(2);
subject.next(3); // 到这里都不会触发 console
subject.complete(); // console: [1, 2, 3]

废弃了的 Transformation Operators

timeoutWith

一句话总结

tap : 处理 side effect

delay : 延迟发布 by 时间

delayWhen : 延迟发布 by Observable

dematerialize : next 可以发布 complete 和 error

materialize : 把 complete 和 error 变成 next 发布

subscribeOn : delay subscribe, 但没有 delay 后续的发布 (放在 pipe 任何位置效果一样)

observeOn : delay 后续的发布, 但是没有 delay 源头 (放在 pipe 的位置不同效果不同)

timeInterval : wrap value with 从上一次发布到这一次的时间间隔

timestamp : wrap value with epoch time

timeout : 超时任务就特殊处理

toArray : 缓存所有 values 直到 complete 后一次性接收 by Array 形式

RxJS 系列 – Utility Operators的更多相关文章

  1. cplusplus系列>utility>pair

    http://www.cplusplus.com/reference/utility/pair/ 用于存储一对异构对象 // Compile: g++ -std=c++11 pair.cpp #inc ...

  2. [RxJS] Utility operator: do

    We just saw map which is a transformation operator. There are a couple of categories of operators, s ...

  3. RxJS——调度器(Scheduler)

    调度器 什么是调度器?调度器是当开始订阅时,控制通知推送的.它由三个部分组成. 调度是数据结构.它知道怎样在优先级或其他标准去存储和排队运行的任务 调度器是一个执行上下文.它表示任务在何时何地执行(例 ...

  4. rxjs笔记(未完成)

    首先是 Observable 和promise的区别, 1返回值个数,Observable 可以返回0到无数个值. 2.Promise主动推送,控制着"值"何时被 "推送 ...

  5. ReactiveX Operators

    This documentation groups information about the various operators and examples of their usage into t ...

  6. [RxJS] Split an RxJS observable with window

    Mapping the values of an observable to many inner observables is not the only way to create a higher ...

  7. RxJS入门2之Rxjs的安装

    RxJS V6.0+ 安装 RxJS 的 import 路径有以下 5 种: 1.创建 Observable 的方法.types.schedulers 和一些工具方法 import { Observa ...

  8. Rxjava, RxAndroid, Retrofit 等库的使用

    RxJava的基本用法: 关于 unSubscribe() 的调用问题: There is no need to unsubscribe in onCompleted. Take a look at  ...

  9. ReactiveX 学习笔记(9)工具类操作符

    Observable Utility Operators 本文的主题为处理 Observable 的实用工具类操作符. 这里的 Observable 实质上是可观察的数据流. RxJava操作符(六) ...

  10. Angular 4+ 修仙之路

    Angular 4.x 快速入门 Angular 4 快速入门 涉及 Angular 简介.环境搭建.插件表达式.自定义组件.表单模块.Http 模块等 Angular 4 基础教程 涉及 Angul ...

随机推荐

  1. 解决方案 | 外接键盘win+d失效,绿联键盘win+d,win+e失效

    按下fn + 右边的win键 即可解决.如下图所示.

  2. mysql Using join buffer (Block Nested Loop) join连接查询优化

    最近在优化链表查询的时候发现就算链接的表里面不到1w的数据链接查询也需要10多秒,这个速度简直不能忍受 通过EXPLAIN发现,extra中有数据是Using join buffer (Block N ...

  3. ps -ef | grep xxx 解释

    上述内容为:命令拆解: ps:将某个进程显示出来-A 显示所有程序.-e 此参数的效果和指定"A"参数相同.-f 显示UID,PPIP,C与STIME栏位.grep命令是查找中间的 ...

  4. [oeasy]python0140_导入_import_from_as_namespace_

    导入import 回忆上次内容 上次学习了 try except   注意要点 半角冒号 缩进 输出错误信息   有错就报告 不要隐瞒 否则找不到出错位置 还可以用traceback把 系统报错信息原 ...

  5. [oeasy]python0010 - python虚拟机解释执行py文件的原理

    ​ 解释运行程序 回忆上次内容 我们这次设置了断点 设置断点的目的是更快地调试 调试的目的是去除​​bug​​ 别害怕​​bug​​ 一步步地总能找到​​bug​​ 这就是程序员基本功 调试​​deb ...

  6. __int128的输入输出(快读快输)

    引言:__int128不能用\(cin\)\(cout\)或\(scanf\)\(printf\). 快读 思想:把每一个字符读入,组成数字. int read(){ int x = 0,y = 1; ...

  7. QT 的 ModelView

    QApplication a(argc, argv); QDirModel model;    //QDirModel,   问文件目录树 QTreeView tree;    QListView l ...

  8. 【MySQL】Tinyint 类型问题

    下发字段: `DISTRIBUTION_STATUS` tinyint(1) DEFAULT '0' COMMENT '下发状态,0未下发,1已下发,2已作废', Mybatis封装之后日志打印也确实 ...

  9. 【Java】关于获取注解的问题发现

    同事设置了个注解,想用Spring获取的Bean来找到Class获取注解 但是发现是空的,在查看的Spring返回Bean之后,发现这个Bean对象并不是原生的实例 而是被Spring代理增强的代理对 ...

  10. 【微信小程序】03 配置项

    全局配置项: https://developers.weixin.qq.com/miniprogram/dev/reference/configuration/app.html 属性 类型 必填 描述 ...