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 ...
随机推荐
- boltdb一瞥
boltdb 网上关于boltdb的文章有很多,特别是微信公众号上,例如: boltdb源码分析系列-事务-腾讯云开发者社区-腾讯云 (tencent.com) 这些文章都写的挺好,但不一定覆盖了我所 ...
- 自学Java第二周
本周学习 一.Java能干些什么? 1.共三个版本:Java SE.Java EE.Java ME Java SE:Java语言的(标准版),用于桌面应用开发,是其他两个版本的基础. Java ME: ...
- Vscode控制台乱码的最终解决方案
Vscode控制台乱码的最终解决方案 vscode运行项目时控制台打印日志乱码.网上也有许多解决办法. 方法一[管用]推荐,避免过多设置 Java项目时,像Springboot微服务项目默认使用的是l ...
- Stopwatch 类来测量时间间隔
使用 Stopwatch 类来测量时间间隔. 以下是一个示例代码,展示如何记录 Excel 导入的用时: ' 创建 Stopwatch 实例 Dim stopwatch As New Stopwatc ...
- 在Python中doc转docx,xls转xlsx,ppt转pptx(Windows)
在Python中doc转docx,xls转xlsx,ppt转pptx(Windows) 说明: 首次发表日期:2024-07-18 参考pypi包: doc2docx 缘起 我们一般使用Python开 ...
- ABC358
A link -- 点击查看代码 #include<bits/stdc++.h> using namespace std; string s,t; signed main(){ cin & ...
- 全网最好看的单细胞umap图绘制教程
全网最好看的单细胞umap图绘制教程 作者按 大家或许都曾被Nature, Science上的单细胞umap图吸引过,不免心生崇拜.在这里,我们将介绍一种简单方便的顶刊级umap图可视化 全文字数|预 ...
- 假期小结8XML之LXML
这桌我初步学习了爬虫相关知识的python库LXML的一些基本用法 以下是我的部分总结 lxml是Python中一个流行的第三方库,用于处理XML和HTML数据.它提供了高效且易于使用的工具,使你能够 ...
- 搭建自动化 Web 页面性能检测系统 —— 部署篇
我们是袋鼠云数栈 UED 团队,致力于打造优秀的一站式数据中台产品.我们始终保持工匠精神,探索前端道路,为社区积累并传播经验价值. 本文作者:琉易 liuxianyu.cn 这一篇是系列文章: 搭建自 ...
- midjourney 生成相似类型图片
生成类似形象 midjourney 核心就是一次运行3次图片,多尝试 上传此图片到discord里的mj -> 复制图片的link -> 使用describe拆词 也可以自己手动拆词,人工 ...