kumavis/obj-multiplex
https://github.com/kumavis/obj-multiplex
obj-multiplex多路复用
simple stream multiplexing for objectMode
其实就是一个多路复用流能够使用name来区分各个子流,以达到一个parent流下其实有多个子流在运行,可以通过多个子流来读入写出数据,效率更高。而且parent流结束了,则所有子流也会被销毁
usage
// create multiplexer
const mux = new ObjMultiplex() // setup substreams
const streamA = mux.createStream('hello')
const streamB = mux.createStream('world') // pipe over transport (and back)
mux.pipe(transport).pipe(mux) // send values over the substreams
streamA.write({ thisIsAn: 'object' })
streamA.write() // or pipe together normally
streamB.pipe(evilAiBrain).pipe(streamB)
obj-multiplex/index.js
const { Duplex } = require('readable-stream')
const endOfStream = require('end-of-stream')//看博客mafintosh/end-of-stream
const once = require('once')
const noop = () => {}
const IGNORE_SUBSTREAM = {}
class ObjectMultiplex extends Duplex {
constructor(_opts = {}) {
const opts = Object.assign({}, _opts, {
objectMode: true,//流可传各类形式数据
})
super(opts)//生成这个流
this._substreams = {}
}
createStream (name) {//就是创建两个流,一个是这个流,另一个是parent是这个流的一个子流,并返回子流
// validate name
if (!name) throw new Error('ObjectMultiplex - name must not be empty')//name不能为空
if (this._substreams[name]) throw new Error('ObjectMultiplex - Substream for name "${name}" already exists')//name不能重复
// create substream
const substream = new Substream({ parent: this, name: name })
this._substreams[name] = substream
// listen for parent stream to end
anyStreamEnd(this, (err) => {//定义当parent流结束,则相应的所有子流也要被销毁
substream.destroy(err)//substream被destroy,如果出错返回的错误信息即err
})
return substream
}
// ignore streams (dont display orphaned data warning)
ignoreStream (name) {//就是将之前创建的name的子流的内容清空
// validate name
if (!name) throw new Error('ObjectMultiplex - name must not be empty')
if (this._substreams[name]) throw new Error('ObjectMultiplex - Substream for name "${name}" already exists')
// set
this._substreams[name] = IGNORE_SUBSTREAM
}
// stream plumbing
//下面就是parent流能够做的一系列读写操作
_read () {}
_write(chunk, encoding, callback) {//当调用 writable.write(chunk) 时,数据会被缓冲在可写流中。
// parse message,就是当parent流write时,将根据其传入的name来决定该数据是写到哪个子流上的
const name = chunk.name
const data = chunk.data
if (!name) {//name不能为空,否则不知道是哪个子流
console.warn(`ObjectMultiplex - malformed chunk without name "${chunk}"`)
return callback()
}
// get corresponding substream
const substream = this._substreams[name]//然后根据name得到子流
if (!substream) {//如果为空则warn
console.warn(`ObjectMultiplex - orphaned data for stream "${name}"`)
return callback()
}
// push data into substream
if (substream !== IGNORE_SUBSTREAM) {//只有当子流不为{}时,才将data压入
substream.push(data)//当调用 stream.push(chunk) 时,数据会被缓冲在可读流中。 如果流的消费者没有调用 stream.read(),则数据会保留在内部队列中直到被消费
}
callback()
}//_write
}//class
class Substream extends Duplex {
constructor ({ parent, name }) {
super({
objectMode: true,
})
this._parent = parent
this._name = name
}
_read () {}//读入的操作即Duplex的定义
_write (chunk, enc, callback) {//当子流被写入时,其实是将数据压入流parent中
this._parent.push({
name: this._name,
data: chunk,
})
callback()//然后调用回调函数
}
}
module.exports = ObjectMultiplex
// util
function anyStreamEnd(stream, _cb) {//就是当stream结束的时候就会调用cb回调函数
const cb = once(_cb)
endOfStream(stream, { readable: false }, cb)
endOfStream(stream, { writable: false }, cb)
}
通过测试学习该库的使用:
obj-multiplex/test/index.js
const test = require('tape')
const once = require('once')
const { PassThrough, Transform } = require('readable-stream')//PassThrough本质也是Transform流,是最简单的Transform流,只是将数据从此处传过
// a passthrough stream.
// basically just the most minimal sort of Transform stream.
// Every written chunk gets output as-is
const endOfStream = require('end-of-stream')
const pump = require('pump')
const ObjMultiplex = require('../index.js')
test('basic - string', (t) => {
t.plan()
const {
inTransport, outTransport,
inMux, outMux,
inStream, outStream,
} = basicTestSetup()
bufferToEnd(outStream, (err, results) => {
t.error(err, 'should not error')
t.deepEqual(results, ['haay', 'wuurl'], 'results should match')
t.end()
})
// pass in messages
inStream.write('haay')
inStream.write('wuurl')
// simulate disconnect
setTimeout(() => inTransport.destroy())
})
test('basic - obj', (t) => {
t.plan()
const {
inTransport, outTransport,
inMux, outMux,
inStream, outStream,
} = basicTestSetup()
bufferToEnd(outStream, (err, results) => {
t.error(err, 'should not error')
t.deepEqual(results, [{ message: 'haay' }, { message: 'wuurl' }], 'results should match')
t.end()
})
// pass in messages
inStream.write({ message: 'haay' })
inStream.write({ message: 'wuurl' })
// simulate disconnect
setTimeout(() => inTransport.destroy())
})
test('roundtrip', (t) => {
t.plan()
const {
inTransport, outTransport,
inMux, outMux,
inStream, outStream,
} = basicTestSetup()
const doubler = new Transform({
objectMode: true,
transform (chunk, end, callback) {//对流内数据进行*2计算
// console.log('doubler!', chunk)
const result = chunk *
callback(null, result)
}
})
pump(//即将从outStream处得到的数据进行*2处理后再传回outStream
outStream,
doubler,
outStream
)
bufferToEnd(inStream, (err, results) => {
t.error(err, 'should not error')
t.deepEqual(results, [, ], 'results should match')
t.end()
})
// pass in messages
inStream.write()
inStream.write()
// simulate disconnect
setTimeout(() => outTransport.destroy(), )
})
// util
function basicTestSetup() {
// setup multiplex and Transport
const inMux = new ObjMultiplex()//定义了两个parent流
const outMux = new ObjMultiplex()
const inTransport = new PassThrough({ objectMode: true })
const outTransport = new PassThrough({ objectMode: true })
// setup substreams
const inStream = inMux.createStream('hello')//分别在两个parent流中各自定义一个name为hello的子流
const outStream = outMux.createStream('hello')
pump(//形成一个pipe流
inMux,
inTransport,
outMux,
outTransport,
inMux
)
return {
inTransport, outTransport,
inMux, outMux,
inStream, outStream,
}
}
function bufferToEnd(stream, callback) {
const results = []
endOfStream(stream, (err) => callback(err, results))//定义了流结束后的回调
stream.on('data', (chunk) => results.push(chunk))//并监听data事件,用于将数据压入流
}
kumavis/obj-multiplex的更多相关文章
- obj.style.z-index的正确写法
obj.style.z-index的正确写法 今天发现obj.style.z-index在js里面报错,后来才知道在js里应该把含"-"的字符写成驼峰式,例如obj.style.z ...
- CSharpGL(9)解析OBJ文件并用CSharpGL渲染
CSharpGL(9)解析OBJ文件并用CSharpGL渲染 2016-08-13 由于CSharpGL一直在更新,现在这个教程已经不适用最新的代码了.CSharpGL源码中包含10多个独立的Demo ...
- BeanUtils.populate(obj, map);
public static void populate(Object bean, Map<String, ? extends Object> properties) throws Ille ...
- VC++ : error LNK2005: ... already defined in *.obj
今天写代码遇到了这么一个链接错误:"已经在*.obj中定义". error LNK2005: "void __cdecl ReplaceWstringVar(class ...
- 111. for(元素变量x:遍历对象obj)
package com.chongrui.test;/* * for(元素变量x:遍历对象obj){ * 引用X的java语句 * * } * * * */public class test { ...
- 让Git忽略所有obj和bin目录的同步
DotNet的项目里,编译出来的二进制文件默认都是放在每个项目对应的bin和obj目录下,有时候开发人员会不小心把这些目录的文件错误的提交到Git服务器.Git里的忽略文件功能可以通过一个.gitig ...
- make: *** [out/host/linux-x86/obj/EXECUTABLES/aidl_intermediates/aidl] 错误 1,make: *** [out/host/linux-x86/obj/lib/libESR_Portable.so] 错误 1
错误3: g++: g++: selected multilib '32' not installed selected multilib '32' not installed make: *** [ ...
- obj转json
.js模型(JSON)的获取 方法一: 1.安装Python插件.安装完后配置环境变量,path中添加Python路径. 2.找到three.js\utils\converters\obj\conve ...
- three.js加载obj模型
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xht ...
随机推荐
- LeetCode子域名访问计数-Python3.7<五>
上一篇:LeetCode 键盘行<四> 题目:https://leetcode-cn.com/problems/subdomain-visit-count/description/ 一个网 ...
- [android] 手机卫士手势滑动切换屏幕
定义手势识别器 获取手势识别器GestureDetector对象,通过new GestureDetector(context,listener),参数:上下文,监听器 匿名内部类实现简单手势监听器Si ...
- 本地计算机上的MySQL服务启动后停止。某些服务在未由其他服务或程序使用时将自动
重新安装MySQL数据库,由于安装的时候马虎,一路next(事实上,某些地方需要严格的配置,我忘记注意了),导致现在出了很多麻烦. 错误信息: 本地计算机上的MySQL服务启动后停止.某些服务在未由其 ...
- Java集合之LinkedList源码分析
概述 LinkedLIst和ArrayLIst一样, 都实现了List接口, 但其内部的数据结构不同, LinkedList是基于链表实现的(从名字也能看出来), 随机访问效率要比ArrayList差 ...
- HTML5的DeviceOrientation实现微信摇一摇功能
在HTML5中,DeviceOrientation特性所提供的DeviceMotion事件封装了设备的运动传感器时间,通过改时间可以获取设备的运动状态.加速度等数据(另还有deviceOrientat ...
- 活字格 QQ 群和客户
上活字格的官网溜达了一圈,有2点收获: 1. 活字格基础教学 QQ 群 这个群居然有1790人!好大的一个群,是不是说明学活字格的人也多呢,我潜水几天看看先 2. 活字格的用户真是各行各业都有,看到他 ...
- 开始记录 Windows Phone 生涯
已经快接近三年没有更新博客了,最近打算把博客这块从新建设起来. 由于工作原因,现在已经很久没有接触过Android了.目前工作是全力 Windows Phone,并且也已经工作一年半了,以后会陆续把之 ...
- JavaScript大杂烩13 - 总结ECMAScript 5新功能
虽说这个标准已经出来很久了,所有的主流浏览器的最新版本也都支持了这些特性,但是很多的教程中并没有包含这个部分,这一节我们专门来总结一下这个标准中的新功能. Object的新方法 在最新的JavaScr ...
- LeetCode题解之 Subtree of Another Tree
1.题目描述 2.问题分析 判断一个节点,然后判断子树. 3.代码 bool isSubtree(TreeNode* s, TreeNode* t) { if (s == NULL) return f ...
- Tensorflow激活函数
注意: 1.大多情况下使用Relu激活函数这种激活函数计算快,且在梯度下降中不会卡在plateaus(平稳段),对于大的输入,也不会饱和. 2.logistic function和hyperbloic ...