网站首页 > 知识剖析 正文
现在我们知道如何创建一个自定义操作符了。为了巩固学到的知识,自己实现一下使用率最高的 map 操作符。我们知道 map 操作符,或者说 map 函数在使用时是要传入一个函数作为参数的,因此我们会得到如下的函数签名:
fn -> source -> source
对照之前 add 操作符的实现,我们有了如下的代码骨架:
import { Subscriber } from 'rxjs';
class MapSubscriber extends Subscriber {}
const map = fn => source => {
return source.lift({
call(sub, source) {
source.subscribe(new MapSubscriber(sub, fn));
}
});
};
现在关键的部分就是如何实现 MapSubscriber 自定义类。继续照抄之前的代码:
class MapSubscriber extends Subscriber {
constructor(subscriber, fn) {
super(subscriber)
this.fn = fn
}
_next(value) {
this.destination.next(this.fn(value));
}
}
其实非常简单,把之前 num 参数换成 fn 参数,只是在最后的 next 中要思考一下,对数据源中的数据做什么操作。在 add 操作符中,我们是对原始值进行加法操作,加的值为我们传入的参数 num。然而在 map 操作符中,我们传入的参数是一个函数,这个函数的目的就是输入一个值,输出另一个值,输出什么,怎么得到新值,都由使用者来决定。因此,我们的实现如上面的代码所示,把数据源中的数据当做参数传给这个函数,函数运行后的结果作为输出继续传给下面的操作符。
一个非官方版的 map 操作符就完成了。
之前的文章我们说过,有两种自定义操作符的方法。一种是 lift 函数,一种是直接在 source 上使用 pipe 函数。其实还有第三种方式,那就是静态版 pipe 函数。我们可以从 rxjs 中导入 pipe函数实现之前的 add 操作符,代码如下:
const add = num => pipe(map(v => v + num));
pipe 的作用就是组合操作符,作为练习,我们同样可以尝试自己来实现以下静态版 pipe 函数。根据 pipe 的使用方式,我们得到以下信息:pipe 可以接收任意多个参数,每个参数都是一个函数,这个函数的签名为 source -> source。pipe 函数的返回值也是一个函数,签名也是 source -> source。因此 pipe 函数的签名为:
fns -> source -> source
有了签名,如何实现呢?试着写一下:
const pipe = (...fns) => source => ... // 省略号的地方怎么写呢?
我们知道 fns 是一堆操作符,也就是一堆 source -> source。伪代码是这样的:
pipe(
source -> source,
source -> source,
...
)
pipe 最终返回的还是个 source -> source。那么其实是不是就是把这些操作符串起来,source从第一个操作符出来传给第二个操作,以此类推,直到最后输出的那个 source。换句话说,每一个操作符的输入都是上一个操作符的输出,变成了这样:
source -> source -> source -> source
熟悉 redux 的朋友肯定觉得眼熟,这不就是一个 reduce 的过程。是的,我们就是要用 reduce函数,因为恰好 fns 就是个数组,实现如下:
const pipe = (...fns) => source => fns.reduce((acc, fn)=> fn(acc), source);
reduce 函数就不讲了,主要看里面的聚合参数怎么写。fn 是操作符函数,acc 是累计值,它的初始值为 source。聚合函数的返回值为 fn(acc) 作为下次运行的累计值。其实这里叫累计值不太合适,其实是用每次运行后的结果覆盖了之前的结果。因为 fn(acc) 的结果还是个 source,恰好可以作为下个操作符运行时的输入参数,这样运行下去直到 fns 耗尽。最后的返回值肯定还是个 source,满足了 pipe 的签名需求。
今天就到这里了,如有任何问题,请添加微信公众号“读一读我”。
猜你喜欢
- 2024-11-14 vue.js正确使用百度地图的方案 vue百度地图自定义控件
- 2024-11-14 七爪源码:如何在 JavaScript 中将 JSON 转换为地图
- 2024-11-14 在地图上创建热力图的方法 怎么用热力图选址
- 2024-11-14 快速了解 ES6 的Map与WeakMap es6 map使用场景
- 2024-11-14 Vue3 + TS + Leafletjs 打造企业级原神大地图
- 2024-11-14 好东西一起用,Cesium.js真是让3D地图尖叫的神奇框架!
- 2024-11-14 为 Next.js 项目创建站点地图文件
- 2024-11-14 JavaScript 轻松获取 Map 中的某个 key
- 2024-11-14 何时使用 Map 来代替普通的 JS 对象
- 2024-11-14 看了几十篇论文实现了个专业算法,用threejs做了个人员定位系统
- 最近发表
-
- Zion无代码,小程序授权和解绑,无代码开发的关键
- 韦德二儿子“变”女儿,韦德支持儿子,与魔术师约翰逊经历相同
- 新鞋速报|Swoosh 面世 50 年!Nike Waffle Trainer 2致敬 Nike 的起源
- 李宁韦德之道2低帮版"踏冰" 球鞋曝光
- Zion又壮了!首秀顶翻1.9亿内线!英格拉姆单臂隔扣
- 音乐手游《zion载音》迎更新 钢琴白发少女免费带回家
- AI 应用赚钱工具哪家强?Coze 和 Zion 对比分析
- 韦德12岁次子完成变性手术,心情雀跃身姿妖娆
- 韦德晒全家福,他穿浴袍像中东土豪,二儿子扎雅比尤尼恩还性感
- 每日NBA球星上脚球鞋「5月12日」(近期nba球星上脚球鞋)
- 标签列表
-
- xml (46)
- css animation (57)
- array_slice (60)
- htmlspecialchars (54)
- position: absolute (54)
- datediff函数 (47)
- array_pop (49)
- jsmap (52)
- toggleclass (43)
- console.time (63)
- .sql (41)
- ahref (40)
- js json.parse (59)
- html复选框 (60)
- css 透明 (44)
- css 颜色 (47)
- php replace (41)
- css nth-child (48)
- min-height (40)
- xml schema (44)
- css 最后一个元素 (46)
- location.origin (44)
- table border (49)
- html tr (40)
- video controls (49)