前言

前几篇介绍过了

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. Sql Server 按日统计产量

    碰到一个这样的需求,需要查询每天的产量,直接 group 是可以分出不同天的产量,但是如果当天没有生产,就会少一条那一天的记录,而不是那一天显示产量为0,这样不方便前端显示曲线. 于是找到下面的办法, ...

  2. 将虚拟机跑在ceph之中

    目录 openStack对接ceph 1. cinder对接ceph 1.1 ceph创建存储池 1.2 ceph授权 1.3 下发ceph文件 1.4 修改globals文件 1.5 部署cinde ...

  3. Bootstrip HTML 查询搜索常用格式模版

    Bootstrip HTML 查询搜索常用格式模版 <form class="form-inline my-3 d-flex align-items-center justify-co ...

  4. Python 实现Excel和TXT文本格式之间的相互转换

    Excel是一种具有强大的数据处理和图表制作功能的电子表格文件,而TXT则是一种简单通用.易于编辑的纯文本文件.将Excel转换为TXT可以帮助我们将复杂的数据表格以文本的形式保存,方便其他程序读取和 ...

  5. 张高兴的 MicroPython 入门指南:(三)使用串口通信

    目录 什么是串口 使用方法 使用板载串口相互通信 硬件需求 电路 代码 使用板载的 USB 串口 参考 什么是串口 串口是串行接口的简称,这是一个非常大的概念,在嵌入式中串口通常指 UART(Univ ...

  6. 手把手教你!STM32单片机入门指南:从初级到中级工程师的学习路线

    ​在当今科技日新月异的时代,嵌入式系统作为智能设备的核心驱动力,正以前所未有的速度渗透到我们生活的方方面面.STM32系列微控制器,以其高性能.低功耗及丰富的外设资源,成了许多开发者踏入嵌入式领域首选 ...

  7. js 做树形数组查询筛选功能

    对二级菜单进行搜索查询: watch: { librarySearch(val) { if(val == '') { this.libraryFiles = this.libraryFilesAll ...

  8. 关于@Mapper与@MapperScan

    o.m.s.mapper.ClassPathMapperScanner : Skipping MapperFactoryBean with name 'gggDao' and 'com.xxx.dao ...

  9. 5/15课下作业:评价一下steam软件

    用户界面: 登录后会弹出特惠广告,广告内容可能不常用.主界面简洁方便,启动游戏,购买游戏,浏览社区,浏览自己内容一目了然 记住用户选择: 登录一次后会记住用户的账户密码,可以直接进行用户间的切换,会记 ...

  10. Jmeter函数助手34-digest

    digest函数用于返回特定哈希算法的加密值. 算法摘要:填入算法,如MD2.MD5.SHA-1.SHA-224.SHA-256.SHA-384.SHA-512 String to be hashed ...