前言

虽然 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的更多相关文章

  1. [RxJS] Error handling operator: catch

    Most of the common RxJS operators are about transformation, combination or filtering, but this lesso ...

  2. [转]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 ...

  3. [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 ...

  4. RxJS——调度器(Scheduler)

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

  5. C++复制对象时勿忘每一部分

    现看这样一个程序: void logCall(const string& funcname) //标记记录 { cout <<funcname <<endl; } cl ...

  6. Flink - DataStream

    先看例子, final StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment(); D ...

  7. 重载new delete操作符是怎么调用的

    自定义的new操作符是怎么对英语new 一个对象的?自定义的delete操作符什么情况下得到调用?new一个对象时出现异常需要我操心内存泄露吗?下面的一个例子帮我们解开所有的疑惑. 1. 调用规则   ...

  8. 算法竞赛向 C++ Standard Library 使用速查

    因网络上 STL 教程大多零散且缺乏严谨性,本文对算法竞赛所需 C++ Standard Library 做了一个较为全面的总结. 全文主要参考以下文档: Containers library - c ...

  9. [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 ...

  10. [RxJS] Creation operator: of()

    RxJS is a lot about the so-called "operators". We will learn most of the important operato ...

随机推荐

  1. 薅 AWS 羊毛的船新方式,以 ChatBot 为例

    还在担心一年免费服务器到期后该怎么办?(Solo社区 投稿) 网上绝大多数薅 AWS 羊毛的教程都是在教大家如何申请创建一年免费的 VPS,太 OUT 了!就问一个问题,一年到期了那咋办? 其实,除了 ...

  2. 24 slide的pdf没有高亮开关

    安卓 app slide的pdf没有高亮开关

  3. 关联的巧妙用法limit_choices_to

    sa_no = models.ForeignKey(CU004HModel, verbose_name='销货单', on_delete=models.PROTECT, related_name='C ...

  4. [oeasy]python0135_变量名与下划线_dunder_声明与赋值

    变量定义 回忆上次内容 变量 就是 能变的量 上次研究了 变量标识符的 规则 第一个字符 应该是 字母或下划线 合法的标识符可以包括 大小写字母 数字 下划线     还研究了字符串(str)的函数 ...

  5. 2023/4/14 SCRUM个人博客

    1.我昨天的任务 初步了解项目的整体框架,并对接下来的人脸识别库以及组件有基本了解和安装 2.遇到了什么困难 ------------ 3.我今天的任务 获得了人脸识别作弊检测和绘制界面的分工,准备先 ...

  6. .NET周刊【7月第4期 2024-07-28】

    国内文章 .NET 高性能缓冲队列实现 BufferQueue https://mp.weixin.qq.com/s/fUhJpyPqwcmb3whuV3CDyg BufferQueue 是一个用 . ...

  7. web3 产品介绍:硬件钱包Ledger 离线管理私钥更安全

    Ledger是一款硬件钱包,可以安全地存储用户的加密资产,并在需要时进行交易.作为一种离线存储设备,Ledger钱包比在线钱包更加安全,因为它能够保护用户的私钥和交易信息,使其免受黑客攻击和网络病毒的 ...

  8. 无缝融入,即刻智能[1]:MaxKB知识库问答系统,零编码嵌入第三方业务系统,定制专属智能方案,用户满意度飙升

    无缝融入,即刻智能[1]:MaxKB知识库问答系统,零编码嵌入第三方业务系统,定制专属智能方案,用户满意度飙升 1.简介 MaxKB(Max Knowledge Base)是一款基于 LLM 大语言模 ...

  9. 【Excel】VBA编程 02 访问MySQL数据库

    1.配置Windows连接驱动ODBC 因为是访问MySQL,则对应的ODBC驱动由MySQL厂商发布 https://dev.mysql.com/downloads/connector/odbc/ ...

  10. 【FastDFS】环境搭建 02 测试

    自带工具测试: 编辑客户端配置文件: vim client.conf 配置完成后,随便上传一个图片到root目录下 运行FastFDS文件上传程序,并将客户端配置文件作为加载参数1,要上传的图片文件位 ...