前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >RxJS的另外四种实现方式(三)——性能最高的库

RxJS的另外四种实现方式(三)——性能最高的库

作者头像
我不是码神
发布2022-07-28 14:20:49
2150
发布2022-07-28 14:20:49
举报
文章被收录于专栏:流媒体技术流媒体技术

接上篇

李宇翔:RxJS的另外四种实现方式(二)——代码最小的库(续)

代码最小的库rx4rx-lite虽然在性能测试中超过了callbag,但和most库较量的时候却落败了,于是我下载了most库,要解开most库性能高的原因。 我们先上一组测试数据,这是在我的windows10 上面跑的

dataflow for 1000000 source events

经过我的不懈努力终于把性能超过了most库。 我先介绍一下fast库的工作原理,下一篇文章我再介绍如何从most库中找到性能提升的要领。

在fast库中,我们开始使用一个基类作为一切操作符的父类,名为Sink。

代码语言:javascript
复制
class Sink {
    constructor(sink, ...args) {
        this.defers = new Set()//用于存放需要释放的操作
        this.sink = sink
        this.init(...args)
        if (sink) sink.defers.add(this)//用于释放的连锁反应
    }
    init() {

    }
    //是否连锁释放
    set disposePass(value) {
        if (!this.sink) return
        if (value)
            this.sink.defers.add(this)
        else this.sink.defers.delete(this)
    }
    //数据向下传递
    next(data) {
        this.sink && this.sink.next(data)
    }
    //完成/error事件向下传递
    complete(err) {
        this.sink && this.sink.complete(err)
        this.dispose(false)
    }
    error(err) {
        this.complete(err)
    }
    //释放即取消订阅功能
    dispose(defer = true) {
        this.disposed = true
        this.complete = noop
        this.next = noop
        this.dispose = noop
        this.subscribes = this.subscribe = noop
        defer && this.defer() //销毁时终止事件源
    }
    defer(add) {
        if (add) {
            this.defers.add(add)
        } else {
            this.defers.forEach(defer => {
                switch (true) {
                    case defer.dispose != void 0:
                        defer.dispose()
                        break;
                    case typeof defer == 'function':
                        defer()
                        break
                    case defer.length > 0:
                        let [f, thisArg, ...args] = defer
                        if (f.call)
                            f.call(thisArg, ...args)
                        else f(...args)
                        break
                }
            })
            this.defers.clear()
        }
    }
    subscribe(source) {
        source(this)
        return this
    }
    subscribes(sources) {
        sources.forEach(source => source(this))
    }
}

为了性能,代码量稍微有点多了。原本传入next和complete函数,现在变为传入sink对象,这里十分类似向Observable传入Observer对象。但是与rxjs不同的是,我们的Observable仍然是一个函数,我们看一个从数组构造Observable的代码

代码语言:javascript
复制
exports.fromArray = array => sink => {
    sink.pos = 0
    const l = array.length
    while (sink.pos < l && !sink.disposed) 
        sink.next(array[sink.pos++])
    sink.complete()
}

这个pos为什么不直接定义一个变量呢?let pos = 0这是常规做法,这里把变量定义到了对象的属性上面,纯粹是为了提高一点点性能,经过测试发现,直接访问(读写操作)局部变量,比访问对象的属性要慢一些。

由于大部分的操作符都是相同的调用方式,所以可以抽象成一个函数

代码语言:javascript
复制
exports.deliver = Class => (...args) => source => sink => source(new Class(sink, ...args))

take操作符就变成了这样

代码语言:javascript
复制
class Take extends Sink {
    init(count) {
        this.count = count
    }
    next(data) {
        this.sink.next(data)
        if (--this.count === 0) {
            this.defer()
            this.complete()
        }
    }
}
exports.take = deliver(Take)

而我们的subscriber就变成了这样

代码语言:javascript
复制
exports.subscribe = (n, e = noop, c = noop) => source => {
        const sink = new Sink()
        sink.next = n
        sink.complete = err => err ? e(err) : c()
        source(sink)
        return sink
    }

至此fast库的基本构建逻辑已经展示完毕。 至于为什么这么快,就请听下回分解。 (未完待续)

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2018-09-21,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • dataflow for 1000000 source events
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档