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

接上篇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函数发送数据,否则啥也不干。

(未完待续)

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,463评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,868评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,213评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,666评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,759评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,725评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,716评论 3 415
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,484评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,928评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,233评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,393评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,073评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,718评论 3 324
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,308评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,538评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,338评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,260评论 2 352

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 172,030评论 25 707
  • 用两张图告诉你,为什么你的 App 会卡顿? - Android - 掘金 Cover 有什么料? 从这篇文章中你...
    hw1212阅读 12,711评论 2 59
  • 那天小朋友起床之后,坐在床边很正式地对我说:“妈妈,我该有个女朋友啦。” 我差不点儿笑出来,一个刚上半年小学的小孩...
    琢爱舟阅读 1,550评论 1 3
  • 一 家乡小城的南面有一条河,一条几近干枯的河。 此河有二、三十米宽,是十几公里外另一条大河的支流。不知从哪年哪月开...
    艺文小舍阅读 747评论 4 26
  • 今天我对自己很狠,我知道。 听说一个朋友的内衣贱卖,我以238元钱买下2件,前不久我是以404买两件,一样的货。 ...
    西瓜甜甜啦阅读 16,852评论 204 238