https://github.com/MetaMask/json-rpc-middleware-stream/blob/master/test/index.js#L20

A small toolset for streaming json rpc and matching requests and responses. Made to be used with json-rpc-engine.

可以用来与json-rpc-engine结合使用的,对输入的json rpc进行读入、写出处理

json-rpc-middleware-stream/index.js

const SafeEventEmitter = require('safe-event-emitter')
const DuplexStream = require('readable-stream').Duplex //即一个可读且可写的流 module.exports = createStreamMiddleware function createStreamMiddleware() {
const idMap = {}
const stream = new DuplexStream({
objectMode: true, //输入的是任意形式的数据,而不非是字符串和 Buffer(或 Uint8Array
read: readNoop, //下面定义的返回false的函数,会覆写_read(),当要从别地流处读出时调用
write: processMessage,//会覆写_write(),当要写入别的流时调用
}) const events = new SafeEventEmitter() const middleware = (req, res, next, end) => {
// write req to stream
stream.push(req)//从req流中读出,就会去调用readNoop函数
// register request on id map
idMap[req.id] = { req, res, next, end }//并在数组中将req根据其id记录下来
} return { events, middleware, stream } function readNoop () {
return false
} function processMessage (res, encoding, cb) {//当要写出时调用
let err
try {
const isNotification = !res.id //如果res.id有值,则isNotification为false;否则为true
if (isNotification) {//res.id没值或为0
processNotification(res)//触发事件'notification'
} else {
processResponse(res)//res.id有值
}
} catch (_err) {
err = _err
}
// continue processing stream
cb(err)
} function processResponse(res) {//将流中内容写出到res流
const context = idMap[res.id] //查看有没有与相应的res.id相同的ID的流之前读入过
if (!context) throw new Error(`StreamMiddleware - Unknown response id ${res.id}`) //如果context为空,则说明相应的id的流并没有读入过,这样写出的时候就不知道要怎么写出了,无end,所以会出错
delete idMap[res.id] //如果有读入过,则写出前先清空idMap中的相应内容
// copy whole res onto original res
Object.assign(context.res, res) //然后将现在要写出到的res流覆写context.res,并返回context.res
// run callback on empty stack,
// prevent internal stream-handler from catching errors
setTimeout(context.end) //调用之前读入时写好的end函数来结束写出操作
} function processNotification(res) {//该事件的监听会在inpage-provider处设置
events.emit('notification', res)
} }
Object.assign(target, ...sources):用于将所有可枚举属性的值从一个或多个源对象复制到目标对象。它将返回目标对象。

json-rpc-middleware-stream/engineStream.js

const DuplexStream = require('readable-stream').Duplex

module.exports = createEngineStream

function createEngineStream({ engine }) {//engine即RpcEngine
if (!engine) throw new Error('Missing engine parameter!')
const stream = new DuplexStream({ objectMode: true, read, write })
// forward notifications
if (engine.on) {
engine.on('notification', (message) => {//监听'notification'事件
stream.push(message) //事件被触发的话就将message数据读入stream,调用read函数
})
}
return stream function read () {
return false
}
function write (req, encoding, cb) {//当写出时调用该函数
engine.handle(req, (err, res) => {
this.push(res)
})
cb()
}
}

测试:

json-rpc-middleware-stream/test/index.js

const test = require('tape')
const RpcEngine = require('json-rpc-engine')
const createJsonRpcStream = require('../index')
const createEngineStream = require('../engineStream') test('middleware - raw test', (t) => { const jsonRpcConnection = createJsonRpcStream()
const req = { id: , jsonrpc: '2.0', method: 'test' }
const initRes = { id: , jsonrpc: '2.0' }
const res = { id: , jsonrpc: '2.0', result: 'test' } // listen for incomming requests
jsonRpcConnection.stream.on('data', (_req) => {//监听data事件
t.equal(req, _req, 'got the expected request')//说明触发data事件传来的
jsonRpcConnection.stream.write(res)//将流中的与res.id相同的数据写出
}) // run middleware, expect end fn to be called
jsonRpcConnection.middleware(req, initRes, () => {//将req流写入createJsonRpcStream
t.fail('should not call next')
}, (err) => {
t.notOk(err, 'should not error')
t.deepEqual(initRes, res, 'got the expected response')
t.end()
}) }) test('engine to stream - raw test', (t) => { const engine = new RpcEngine()
engine.push((req, res, next, end) => {
res.result = 'test'
end()
}) const stream = createEngineStream({ engine })
const req = { id: , jsonrpc: '2.0', method: 'test' }
const res = { id: , jsonrpc: '2.0', result: 'test' } // listen for incomming requests
stream.on('data', (_res) => {
t.deepEqual(res, _res, 'got the expected response')
t.end()
}) stream.on('error', (err) => {
t.fail(error.message)
}) stream.write(req) }) test('middleware and engine to stream', (t) => {//上面两者的结合 // create guest
const engineA = new RpcEngine()
const jsonRpcConnection = createJsonRpcStream()
engineA.push(jsonRpcConnection.middleware) // create host
const engineB = new RpcEngine()
engineB.push((req, res, next, end) => {
res.result = 'test'
end()
}) // connect both
const clientSideStream = jsonRpcConnection.stream
const hostSideStream = createEngineStream({ engine: engineB })
clientSideStream
.pipe(hostSideStream)
.pipe(clientSideStream) // request and expected result
const req = { id: , jsonrpc: '2.0', method: 'test' }
const res = { id: , jsonrpc: '2.0', result: 'test' } engineA.handle(req, (err, _res) => {//req调用jsonRpcConnection.middleware读入clientSideStream,然后hostSideStream从clientSideStream中读入req数据,然后调用engineB的方法写出,所以得到的result: 'test'
t.notOk(err, 'does not error')
t.deepEqual(res, _res, 'got the expected response')
t.end()
}) }) test('server notification', (t) => {
t.plan() const jsonRpcConnection = createJsonRpcStream()
const notif = { jsonrpc: '2.0', method: 'test_notif' }//这里没有设置id,所以调用write所以会触发processNotification函数,触发'notification'事件 jsonRpcConnection.events.once('notification', (message) => {
t.equals(message.method, notif.method)
t.end()
}) // receive notification
jsonRpcConnection.stream.write(notif)
}) test('server notification in stream', (t) => {
const engine = new RpcEngine() const stream = createEngineStream({ engine })
const notif = { jsonrpc: '2.0', method: 'test_notif' } // listen for incomming requests
stream.once('data', (_notif) => {
t.deepEqual(notif, _notif, 'got the expected notification')
t.end()
}) stream.on('error', (err) => {
t.fail(error.message)
}) engine.emit('notification', notif)//将触发createEngineStream中的'notification'事件,notif将被读入stream,将触发data事件
})

MetaMask/json-rpc-middleware-stream的更多相关文章

  1. 測试JSON RPC远程调用(JSONclient)

    #include <string> #include <iostream> #include <curl/curl.h> /* 标题:JSonclient Auth ...

  2. MetaMask/metamask-inpage-provider

    https://github.com/MetaMask/metamask-inpage-provider Used to initialize the inpage ethereum provider ...

  3. metamask源码学习-metamask-controller.js

    The MetaMask Controller——The central metamask controller. Aggregates other controllers and exports a ...

  4. metamask源码学习-inpage.js

    The most confusing part about porting MetaMask to a new platform is the way we provide the Web3 API ...

  5. Guide to Porting MetaMask to a New Environment

    https://github.com/MetaMask/metamask-extension/blob/develop/docs/porting_to_new_environment.md MetaM ...

  6. 【.NET Core项目实战-统一认证平台】第十六章 网关篇-Ocelot集成RPC服务

    [.NET Core项目实战-统一认证平台]开篇及目录索引 一.什么是RPC RPC是"远程调用(Remote Procedure Call)"的一个名称的缩写,并不是任何规范化的 ...

  7. metamask源码学习-contentscript.js

    When a new site is visited, the WebExtension creates a new ContentScript in that page's context, whi ...

  8. MetaMask/json-rpc-engine

    https://github.com/MetaMask/json-rpc-engine RpcEngine——MetaMask/json-rpc-engine https://github.com/M ...

  9. 以太坊RPC机制与API实例

    上一篇文章介绍了以太坊的基础知识,我们了解了web3.js的调用方式是通过以太坊RPC技术,本篇文章旨在研究如何开发.编译.运行与使用以太坊RPC接口. 关键字:以太坊,RPC,JSON-RPC,cl ...

随机推荐

  1. C#中Lambda表达式总结

    在C#的语法中有一种比较特殊的写法,叫做Lambda表达式,这种表达式的写法在于你查询数据的时候直接是使用以下箭头的形式来表示查询语句的:=>.例如,我们要查找学生的List<Studen ...

  2. C#中的readonly跟const用法小结

    总结一下常量和只读字段的区别: 由来: 笔者也是在看欧立奇版的<.Net 程序员面试宝典>的时候,才发现自己长久以来竟然在弄不清出两者的情况下,混用了这么长的时间.的确,const与rea ...

  3. soapui 自动化教程

    本教程主要讲述对接口的自动化测试,略过压力测试.安全测试. 最终目标是通过groovy脚本执行一个文件,发送多个任务请求.验证返回值是否符合期望. 教程从soapui入门到groovy实现回传参数.生 ...

  4. 微信公共号:CTO技术总监

    业务价值胜过技术策略: 战略目标胜过具体项目的效益: 内置的互操作胜过定制的集成: 共享服务胜过特定目标的实现: 灵活性胜过优化: 不断演进地提炼胜过在最开始追求完美!

  5. loj#2509. 「AHOI / HNOI2018」排列(思维题 set)

    题意 题目链接 Sol 神仙题Orz 首先不难看出如果我们从\(a_i\)向\(i\)连一条边,我们会得到以\(0\)为根的树(因为每个点一定都有一个入度,出现环说明无解),同时在进行排列的时候需要保 ...

  6. VUE 配置vue-devtools调试工具

    1. 通过 Git 克隆项目到本地 git clone https://github.com/vuejs/vue-devtools.git 2. Git 进入到 vue-devtools 所在目录,然 ...

  7. Windows下使用Rtools编译R语言包

    使用devtools安装github中的R源代码时,经常会出各种错误,索性搜了一下怎么在Windows下直接打包,网上的资料也是参差不齐,以下是自己验证通过的. 一.下载Rtools 下载地址:htt ...

  8. Apache POI导出excel表格

    项目中我们经常用到导出功能,将数据导出以便于审查和统计等.本文主要使用Apache POI实现导出数据. POI中文文档 简介 ApachePOI是Apache软件基金会的开放源码函式库,POI提供A ...

  9. maven(四):一个基本maven项目的pom.xml配置

    继续之前创建的test项目,一个基本项目的pom.xml文件,通常至少有三个部分 第一部分,项目坐标,信息描述等 <modelVersion>4.0.0</modelVersion& ...

  10. [20180718]拷贝数据文件从dg库.txt

    [20180718]拷贝数据文件从dg库.txt 1.测试环境:SCOTT@book> @ ver1PORT_STRING                    VERSION        B ...