2019独角兽企业重金招聘Python工程师标准>>>

接上篇RxJS的另外四种实现方式(序)

起因

想到这个库的原因,是看了callbag库想到的,callbag库的原理大家可以自己找资料了解,我就不多赘述,我只谈谈我的理解。callbag的设计思路是把消费者和生产者合并成一个,通过互相传递一个回调函数实现通讯。看过部分操作符实现原理的同学肯定觉得逻辑十分难解,因为过多的回调使得你的脑回路不够用了。我用了一些库函数后,我意识到,其实不需要如此复杂的设计,为什么呢?请看下文

大同小异的callbag

callbag里面有很多代码是重复书写的,原因很简单,功能是确定的,如订阅功能,这是必不可少的操作,下面我来比较一下我的库的实现和callbag的实现。

对比实现生产者interval

先上callbag的源码

const interval = period => (start, sink) => {if (start !== 0) return;let i = 0;const id = setInterval(() => {sink(1, i++);}, period);sink(0, t => {if (t === 2) clearInterval(id);});
};export default interval;

说明一下

if(start!=0)return

这句话在callbag实现库里面随处可见,我就是因为这句话引起的思考,为什么每次都要重复写呢? 当然是因为这是一个生产者,只发送数据,不会去接受数据。

  sink(0, t => {if (t === 2) clearInterval(id);});

上面这段代码其实是实现了一个取消订阅功能,实现方法是向传来的回调函数再传回一个回调函数,估计读者脑子要烧糊了。

上面这个interval可观察对象的原型可以代表大多数的callbag的案例,那么有没有办法用更为简洁的方式实现呢?

ShowTime

exports.interval = period => n => {let i = 0;const id = setInterval(() => n(i++), period)return () => clearInterval(id)
}

什么,只有这么几行代码吗?,没错,这就是我认为实现代码最小的库了,不服来战。此代码不仅小,性能好,还通俗易懂。当然我还是得稍微解释一下要使得interval(1000)成为一个地道的生产者,必须要实现可以订阅,可以取消订阅,以及可以得到生产者发出的数据(有些还需要得到complete和error事件,interval不会complete也不会error)

  • interval(1000)将得到一个函数n=>……,这个函数接受一个next函数用于发送数据
  • 调用interval(1000)这个高阶函数等同于“订阅”,此处是重点(代替了callbag中发送type为0的行为)
  • 返回的是一个dispose函数,即用于“取消订阅”的功能(代替了callbag中传回一个回调并在里面接受type为2的行为)
  • 函数中调用了传入的next函数n,即发送出去了数据

当然interval不会独立工作,我们需要更多的操作符和观察者使得库来运作。

对比操作符filter

下面是callbag的实现

const filter = condition => source => (start, sink) => {if (start !== 0) return;let talkback;source(0, (t, d) => {if (t === 0) {talkback = d;sink(t, d);} else if (t === 1) {if (condition(d)) sink(t, d);else talkback(1);}else sink(t, d);});
};module.exports = filter;

依然出现了

if(start!=0)return

没错,因为filter只用于被订阅,本身作为数据响应者,有人说不对,filter需要对上一级的源做响应,没错,所以需要订阅上一级的源,但传入的不是自身,而是另一个回调函数来响应,否则就会有问题。核心代码就一句,却需要一大堆代码来维持正常运行,我看不下去了。

ShowTime

exports.filter = f => source => (n, c) => source(d => f(d) && n(d), c)

What?就一行代码?你没看错,你没看错,你没看错! 我来解释一下,这一行代码。filter是一个操作符,filter(d=>d>1)代表我只接受大于1的数据,这个将返回一个source=>……的函数,这个函数接受一个source作为上一级数据源,可以是上文的interval(1000)这样的生产者,也可以是其他操作符。所以

const obserable = filter(d => d > 1)(interval(1000))

你将得到一个(n,c)=>……的函数,这个就是可观察者,你可以传入next函数n,和complete函数c来进行“订阅”了

const disposable = obserable(d => console.log('得到',d),err => console.log('完成'))//err代表有错误,这里先不处理

你订阅过后会得到一个函数disposable,用于“取消订阅”

disposable()//取消订阅

这个filter代表了最小库的精髓:disposable可以从箭头函数一路返回,在filter中是隐含的,无需显示实现而代表complete的c函数也是直接透传,无需更改。唯独需要操作的就是next函数,需要向source传一个新的next函数。当满足条件时就向下一级的next函数发送数据,否则啥也不干。

(未完待续)

转载于:https://my.oschina.net/langhuihui/blog/2051770

RxJS的另外四种实现方式(一)——代码最小的库相关推荐

  1. 【读MFiX源代码】MFiX中四种传热方式全面详解(对流、导热、辐射、反应热)并且输出以供后处理(2020-12-15更新)

    文章目录 1 目标 2 代码结构 2.1 des_time_step外层总控制 2.2 颗粒导热 2.2.1 颗粒-颗粒导热:calc_force_dem.f和des_thermo_cond_mod. ...

  2. JAVA四种引用方式

    JAVA四种引用方式: java.lang.ref: 强引用(直接变量赋值) 软引用(SoftReference): 只有在要发生OOM错误之前才会回收掉老的软引用对象,应用场景主要防止内存溢出.(缓 ...

  3. 矩阵乘法的四种理解方式

    先介绍向量的两种运算,一个行向量乘以一个列向量称作向量的内积,又叫作点积,结果是一个数: 一个列向量乘以一个行向量称作向量的外积,外积是一种特殊的克罗内克积,结果是一个矩阵, 假设和b分别是一个行向量 ...

  4. 【Android】android开发之splash闪屏页的四种实现方式,启动页的实现教程。

    2019独角兽企业重金招聘Python工程师标准>>> 作者:程序员小冰,GitHub主页: https://github.com/QQ986945193 新浪微博:http://w ...

  5. sqlserver的四种分页方式

    第一种:ROW_NUMBER() OVER()方式 select * from ( select *, ROW_NUMBER() OVER(Order by ArtistId ) AS RowId f ...

  6. 【Python基础】Python爬虫的两套解析方法和四种信息提取方式

    Python爬虫 Author:Iouwill Machine Learning Lab 分享一篇往日旧文章,非常实用. 对于大多数朋友而言,爬虫绝对是学习python的最好的起手和入门方式.因为爬虫 ...

  7. OAuth2.0的四种授权方式

    在OAuth2.0中,OAuth2.0 provider负责保护暴露在外的资源,第三方应用客户端Client可以独立的或代表用户Owner来访问这些受保护的资源,provider提供token令牌的管 ...

  8. php xml 四种,xml中常见的四种解析方式是什么?

    xml解析方式有:1.DOM解析方法,可以对xml文档进行修改操作:2.SAX解析方法,解析速度快,占用内存少:3.JDOM解析方法,查找方便:4.DOM4J解析方法,解析XML的速度快. 在XML的 ...

  9. 对require四种引入方式的认识

    对require四种引入方式的认识: 转载于:https://www.cnblogs.com/461770539-qq/p/9357485.html

最新文章

  1. System Landscape Recommendations for SAP Customer Activity Repository
  2. centos7中安装、配置、验证、卸载redis
  3. 【零基础入门数据挖掘】-模型融合
  4. xstat博客主题php,WordPress博客主题:Diaspora 简约文艺范主题
  5. Linq--使用Linq在不同类型之间转换
  6. Android TabHost和xml定义Menu应用
  7. linux 远程赋值,linux 简单远程复制命令scp参数
  8. 基于遥感影像实现三种方法提取枣树面积精度分析
  9. cuda无法在你的电脑上运行_解决“此应用无法在你的电脑上运行”
  10. 吞吐量、响应时间和 CPU 利用率之间的关系
  11. MATLAB 软件安装与无法打开问题
  12. 阿里云图片拼接指定尺寸
  13. TPMS烧录器安装 SNP739
  14. 81-RabbitMQ详解
  15. BZOJ4340:[BJOI2015]隐身术(后缀数组,ST表,DFS)
  16. 至少12亿元收支差,分析运营商7大数据产品应用
  17. 五款轻量级的办公软件,界面简洁且无广告
  18. ps play android下载地址,PSPlay
  19. Matlab 2014a安装文件下载、安装教程及破解教程!!!
  20. Xshell远程操作liunx图形化桌面

热门文章

  1. 修改 “嗨加游-Prefix.pch” 或者 “嗨加游-Info.plist ” 方法
  2. Cocos2d API 解析之Texture2d
  3. DevExpress ActiveX
  4. 20190228 搭建Hadoop基础环境
  5. 深入理解Spring之九:DispatcherServlet初始化源码分析
  6. linux中的权限对于文件和目录的重要性
  7. (转)EXCEL2007存储格式xlsx
  8. 软件编程,在于设计和思想
  9. 让搜索显示中文的方法
  10. MySQL 5.7主从复制从零开始设置及全面详解——实现多线程并行同步,解决主从复制延迟问题!