RxJS 系列 – Custom Operator
前言
虽然 RxJS 提供了非常多的 Operators. 但依然会有不够用的时候. 这时就可以自定义 Operator 了.
Operator Is Just a Function Observable => Observable
Operator 只是一个函数.
timer(1000).pipe(obs => obs).subscribe();
它接收一个 Observable 返回一个 Observable.
Operator 都是放在管道 (pipe) 内的, 所以从源头 Observable 一直传递下去.
每一个 Operator 接收 upstream(上游) 的 Observable 并且返回一个 Observable (通常是新的一个) 给 downstream(下游).
每一个 Operator 就是对发布值的加工处理.
Standard Operator
source 源头
首先我们有个源头
const source = timer(1000);
每一秒发布一次
Upstream / Downstream Observable
接着搞一个 pipe 和 operator.
const source = timer(1000);
source
.pipe(upstreamObs => {
console.log(upstreamObs === source); // true const downstreamObs = new Observable();
return downstreamObs;
})
.subscribe(v => console.log(v));
可以看到 operator 函数接收的就是 upstream 的 Observable, 然后返回一个新的 Observable 到 downstream.
Connect Upstream and Downstream
downstream to upstream
当 downstream 被 subscribe, 我们 subscribe upstream
当 downstream 被 unsubscribe, 我们 unsubscribe upstream
const source = timer(1000);
source
.pipe(upstreamObs => {
const downstreamObs = new Observable(subscriber => { // 当 downstream Observable 被订阅以后, 我们才订阅 upstream Observable
const upstreamSub = upstreamObs.subscribe(); return () => {
// 当 downstream 被退订以后, 我们也要退订 upstream Observable
upstreamSub.unsubscribe();
}; }); return downstreamObs;
})
.subscribe(v => console.log(v));
upstream to downstream
当接收到 upstream 发布时, 我们也发布到 downstream
const downstreamObs = new Observable(subscriber => {
const upstreamSub = upstreamObs.subscribe({
next: upstreamValue => {
const downStreamValue = upstreamValue + 'downstream value'; // decorate value for downstream
subscriber.next(downStreamValue); // 发布到 downstream
},
error: error => subscriber.error(error), // 转发去 downstream
complete: () => subscriber.complete(), // 转发去 downstream
});
return () => {
upstreamSub.unsubscribe();
};
});
小结
从上面几招可以看出来, 主要就是 upstream 和 downstream 中间的关系.
如何订阅, 退订, 发布 value 等等. 上面只是给一个简单直观的例子. 真实场景中, upstream 和 downstream 发布时机, 往往是不一致的 (比如 upstream 发布 1 次后, downstream 可能发布多次)
Operator with Config
只要把 Operator 包装成工厂函数就可以支持 Config 了
function myOperator(config: { dependObs: Observable<unknown> }): OperatorFunction<number, string> {
const { dependObs }= config;
return upstreamObs => {
const downstreamObs = new Observable<string>(subscriber => {
// 订阅 depend
const dependObsSub = dependObs.subscribe(() => console.log('do something'));
const upstreamSub = upstreamObs.subscribe({
next: upstreamValue => {
const downStreamValue = upstreamValue + 'downstream value'; // decorate value for downstream
subscriber.next(downStreamValue); // 发布到 downstream
},
error: error => subscriber.error(error), // 转发去 downstream
complete: () => {
// 释放 depend
dependObsSub.unsubscribe();
subscriber.complete();
},
});
return () => {
upstreamSub.unsubscribe();
// 释放 depend
dependObsSub.unsubscribe();
};
});
return downstreamObs;
};
}
const source = timer(1000);
const dependObs = new Subject();
source.pipe(myOperator({ dependObs })).subscribe(v => console.log(v));
一个 Factory 函数, 通过配置生产 Operator。
OperatorFunction 定义了 Operator 接口, 它是加入了泛型的 Observable => Observable.
如果 upstream 和 downstream 的类型是一样的话可以用它的简化版本 MonoTypeOperatorFunction<T>

Unsubscribe dependency stream
比如说像 takeUntil operator
const obs = timer(0, 1000); // 0..1..2..3..4..5
obs.pipe(takeUntil(timer(3000))).subscribe(v => console.log(v)); // 0..1..2
它内部会 subscribe timer$,timer$ 就是它的 dependency observable。
如果在还没有到 3 秒的时候,这个 observable 就被 unsubscribe 了,那 takeUntil operator 内部就要提前去 unsubscribe timer$。
同理,如果这个 observable 在还没有到 3 秒的时候,就被 error 或 complete 了,那 takeUntil operator 内部也需要提前去 unsubscribe timer$。
总之,我们在设计 operator 时,一定要顾虑到 upstream 的 error / complete 和 downstream 的 unsubscribe 对 dependency observable 的影响。
RxJS 系列 – Custom Operator的更多相关文章
- [RxJS] Error handling operator: catch
Most of the common RxJS operators are about transformation, combination or filtering, but this lesso ...
- [转]VS Code 扩展 Angular 6 Snippets - TypeScript, Html, Angular Material, ngRx, RxJS & Flex Layout
本文转自:https://marketplace.visualstudio.com/items?itemName=Mikael.Angular-BeastCode VSCode Angular Typ ...
- [RxJS] Learn How To Use RxJS 5.5 Beta 2
The main changes is about how you import rxjs opreators from now on. And introduce lettable opreator ...
- RxJS——调度器(Scheduler)
调度器 什么是调度器?调度器是当开始订阅时,控制通知推送的.它由三个部分组成. 调度是数据结构.它知道怎样在优先级或其他标准去存储和排队运行的任务 调度器是一个执行上下文.它表示任务在何时何地执行(例 ...
- C++复制对象时勿忘每一部分
现看这样一个程序: void logCall(const string& funcname) //标记记录 { cout <<funcname <<endl; } cl ...
- Flink - DataStream
先看例子, final StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment(); D ...
- 重载new delete操作符是怎么调用的
自定义的new操作符是怎么对英语new 一个对象的?自定义的delete操作符什么情况下得到调用?new一个对象时出现异常需要我操心内存泄露吗?下面的一个例子帮我们解开所有的疑惑. 1. 调用规则 ...
- 算法竞赛向 C++ Standard Library 使用速查
因网络上 STL 教程大多零散且缺乏严谨性,本文对算法竞赛所需 C++ Standard Library 做了一个较为全面的总结. 全文主要参考以下文档: Containers library - c ...
- [RxJS] Create a Reusable Operator from Scratch in RxJS
With knowledge of extending Subscriber and using source.lift to connect a source to a subscriber, yo ...
- [RxJS] Creation operator: of()
RxJS is a lot about the so-called "operators". We will learn most of the important operato ...
随机推荐
- Git 奇幻之旅⌛️续集
第十二天:暂存未完成的修改 小明和小红在开发一个新功能时,他们需要切换到另一个分支去修复一个紧急的 bug .但是他们的当前分支上还有一些未完成的修改,他们不想提交这些修改,也不想丢弃这些修改.有一天 ...
- 搭建lnmp环境-mysql(第五步)
版本mysql 5.7 先删除系统自带的db 新建文件夹/data/download 进入后下载 wget http://repo.mysql.com/mysql57-community-releas ...
- 写写stream流的终结操作
终结操作和中间操作的区别:中间操作返回的一直都是stream,所以可以一直使用,但是终结操作返回的不是stream,后面不能继续操作 foreach:对流中的所有元素进行遍历操作 count:获取当前 ...
- axios传递参数的使用
今天在学习elasticsearch时,遇到一个问题:项目中前端采用的是Vue2+axios,后端的接口采用Restful风格来接收: 关于Resultful风格: 1. GET(SELECT):从服 ...
- 【Java】Annotation 注解
Annotation 注解 注解是一种元数据 MetaData,从JDK5开始 在Java代码中是一个特殊的标记,可以在编译,类加载,运行时读取,执行对应的处理 程序可以在不改变原有逻辑的基础上嵌入一 ...
- 【Java】JDBC Part2 工具类封装实现
JDBC 工具类封装实现 - 注册和配置都放在静态代码块完成 - 静态方法获取连接,和释放资源 - 本类不产生实例 - 5版本 + 已经可以实现无驱动注册,所以驱动部分注释了 package cn.d ...
- 【Vue】15 VueX
[什么是VueX?] VueX是一个专门为Vue.js应用程序开发的状态管理模式, 采用集中式存储管理应用的所有组件状态, 以相应的规则保证按照一种可预测的方式发生改变. 即把多个组件的变量统一放到一 ...
- 如何查看华为的大模型(AI模型),华为官方的mindspore下的大模型???
由于华为官方的mindspore网站的设计比较反人性话,操作起来十分的复杂,因此如果想要在华为的官方网站上查找这个华为的官方大模型还是比较困难的,为此直接给出链接地址. PS. 要注意,华为的AI官方 ...
- 同策略强化学习算法可以使用经验缓存池(experience buffer)吗 ??? 设计一个基于缓存池的改进reinforce算法,给出初步的尝试 ---------- (reinforce + experience buffer)
本文使用代码地址: https://gitee.com/devilmaycry812839668/reinforce_with_-experience-buffer ================= ...
- win10系统wifi不会自动连接怎么解决
参考: https://jingyan.baidu.com/article/d621e8da743bab2865913f99.html ================================ ...