MetaMask/json-rpc-engine

https://github.com/MetaMask/json-rpc-enginegit

RpcEngine——MetaMask/json-rpc-engine

https://github.com/MetaMask/json-rpc-enginegithub

a tool for processing JSON RPCjson

usage

const RpcEngine = require('json-rpc-engine') let engine = new RpcEngine()

Build a stack of json rpc processors by pushing in RpcEngine middleware.異步

經過push RpcEngine中間件構建一個json rpc處理器堆棧,處理步驟爲先進後出,handle時獲得的結果是與push時做出的處理相關的async

engine.push(function(req, res, next, end){
  res.result = 42 end() })

⚠️push是可以對以後handle傳入的request(即json rpc的值進行處理,(req, res, next, end)中的req就是handle傳入的request)的一些狀態進行定義或做出一些相關處理,會在handle處理json rpc時對其形成影響。ide

好比若是在push中設置res.result = req.id,那麼就是將json rpc中傳進來的(id: 1)的值傳出函數

res:返回的是在push中通過處理後的json rpc的值,若是push中什麼都沒有作,那麼req與res的值是相同的測試

 

JSON RPC are handled asynchronously, stepping down the stack until complete.異步處理request,直到返回結果ui

let request = { id: 1, jsonrpc: '2.0', method: 'hello' } engine.handle(request, function(err, res){ // do something with res.result,res.result即爲push中設置的true })

 

RpcEngine middleware has direct access to the request and response objects. It can let processing continue down the stack with next() or complete the request with end().RpcEngine中間件能夠直接訪問請求和響應對象。它可使用next()繼續處理堆棧,也可使用end()完成請求url

engine.push(function(req, res, next, end){
  if (req.skipCache) return next() res.result = getResultFromCache(req) end() })

 

By passing a 'return handler' to the next function, you can get a peek at the result before it returns.

經過將「返回處理程序」傳遞給下一個函數,您能夠在結果返回以前看到它

engine.push(function(req, res, next, end){
  next(function(cb){//就是先壓入堆棧中,不進行處理,等到因此push都解決完後再返回處理
    insertIntoCache(res, cb)
  })
})
 

RpcEngines can be nested by converting them to middleware asMiddleware(engine)。rpcengine能夠經過將它們轉換爲中間件(中間件)來嵌套

const asMiddleware = require('json-rpc-engine/lib/asMiddleware') let engine = new RpcEngine() let subengine = new RpcEngine() engine.push(asMiddleware(subengine))

 

gotchas陷阱

Handle errors via end(err), NOT next(err).解決error使用的是end(),而不是next()

/* INCORRECT */ engine.push(function(req, res, next, end){ next(new Error()) }) /* CORRECT */ engine.push(function(req, res, next, end){ end(new Error()) })

 

json-rpc-engine/test/basic.spec.js

舉例說明:

/* eslint-env mocha */ 'use strict' const assert = require('assert') const RpcEngine = require('../src/index.js') describe('basic tests', function () {  it('basic middleware test', function (done) { let engine = new RpcEngine() engine.push(function (req, res, next, end) { req.method = 'banana' res.result = 42 end() }) let payload = { id: 1, jsonrpc: '2.0', method: 'hello' } engine.handle(payload, function (err, res) { assert.ifError(err, 'did not error') assert(res, 'has res') assert.equal(res.result, 42, 'has expected result') assert.equal(payload.method, 'hello', 'original request object is not mutated by middleware') //payload.method仍然是'hello',而不會被改爲'banana' done() }) }) it('interacting middleware test', function (done) { //兩個push交互 let engine = new RpcEngine() engine.push(function (req, res, next, end) { req.resultShouldBe = 42 next() }) engine.push(function (req, res, next, end) { res.result = req.resultShouldBe end() }) let payload = { id: 1, jsonrpc: '2.0', method: 'hello' } engine.handle(payload, function (err, res) { assert.ifError(err, 'did not error') assert(res, 'has res') assert.equal(res.result, 42, 'has expected result') done() }) }) it('erroring middleware test', function (done) { let engine = new RpcEngine() engine.push(function (req, res, next, end) { end(new Error('no bueno'))//定義一個錯誤 }) let payload = { id: 1, jsonrpc: '2.0', method: 'hello' } engine.handle(payload, function (err, res) { assert(err, 'did error') //測試發現有錯,push中定義的 assert(res, 'does have response') assert(res.error, 'does have error on response') done() }) }) it('empty middleware test', function (done) { let engine = new RpcEngine() let payload = { id: 1, jsonrpc: '2.0', method: 'hello' } //若是沒有push ,handle將報錯 engine.handle(payload, function (err, res) { assert(err, 'did error') done() }) }) it('handle batch payloads', function (done) { let engine = new RpcEngine() engine.push(function (req, res, next, end) { res.result = req.id end() }) let payloadA = { id: 1, jsonrpc: '2.0', method: 'hello' } let payloadB = { id: 2, jsonrpc: '2.0', method: 'hello' } let payload = [payloadA, payloadB] //能夠一會兒handle多個push engine.handle(payload, function (err, res) { assert.ifError(err, 'did not error') assert(res, 'has res') assert(Array.isArray(res), 'res is array') assert.equal(res[0].result, 1, 'has expected result') assert.equal(res[1].result, 2, 'has expected result') done() }) }) 

json-rpc-engine/test/asMiddleware.spec.js

/* eslint-env mocha */ 'use strict' const assert = require('assert') const RpcEngine = require('../src/index.js') const asMiddleware = require('../src/asMiddleware.js') describe('asMiddleware', function () { //嵌套 it('basic', function (done) { let engine = new RpcEngine() let subengine = new RpcEngine() let originalReq subengine.push(function (req, res, next, end) { originalReq = req res.result = 'saw subengine' end() }) engine.push(asMiddleware(subengine))//將兩種嵌套,那麼engine就可以使用subengine在push時的定義 let payload = { id: 1, jsonrpc: '2.0', method: 'hello' } engine.handle(payload, function (err, res) { assert.ifError(err, 'did not error') assert(res, 'has res') assert.equal(originalReq.id, res.id, 'id matches') assert.equal(originalReq.jsonrpc, res.jsonrpc, 'jsonrpc version matches') assert.equal(res.result, 'saw subengine', 'response was handled by nested engine') done() }) }) })

 

 

 

 

 

json-rpc-engine/src/idRemapMiddleware.js

const getUniqueId = require('./getUniqueId') module.exports = createIdRemapMiddleware function createIdRemapMiddleware() { return (req, res, next, end) => { const originalId = req.id const newId = getUniqueId() req.id = newId res.id = newId next((done) => { req.id = originalId res.id = originalId done() }) } }

測試:

json-rpc-engine/test/idRemapMiddleware.spec.js

/* eslint-env mocha */ 'use strict' const assert = require('assert') const RpcEngine = require('../src/index.js') const createIdRemapMiddleware = require('../src/idRemapMiddleware.js') describe('idRemapMiddleware tests', function () { it('basic middleware test', function (done) { let engine = new RpcEngine() const observedIds = { before: {}, after: {}, } engine.push(function (req, res, next, end) { observedIds.before.req = req.id observedIds.before.res = res.id //設置使得handle時 res.id = req.id,二者結果相同 next() }) engine.push(createIdRemapMiddleware()) engine.push(function (req, res, next, end) { observedIds.after.req = req.id observedIds.after.res = res.id // set result so it doesnt error res.result = true end() }) let payload = { id: 1, jsonrpc: '2.0', method: 'hello' } const payloadCopy = Object.assign({}, payload) engine.handle(payload, function (err, res) { assert.ifError(err, 'did not error') assert(res, 'has res') // collected data assert(observedIds.before.req, 'captured ids') assert(observedIds.before.res, 'captured ids') assert(observedIds.after.req, 'captured ids') assert(observedIds.after.res, 'captured ids') // data matches expectations assert.equal(observedIds.before.req, observedIds.before.res, 'ids match') //一開始兩個是相同的 assert.equal(observedIds.after.req, observedIds.after.res, 'ids match') //以後兩個的結果也是相同的,可是變成了newId // correct behavior assert.notEqual(observedIds.before.req, observedIds.after.req, 'ids are different') //先後的req.id不一樣了 assert.equal(observedIds.before.req, res.id, 'result id matches original') //可是before和最後輸出的結果res.id仍是同樣的 assert.equal(payload.id, res.id, 'result id matches original') assert.equal(payloadCopy.id, res.id, 'result id matches original') done() }) }) })

這裏能夠知道idRemapMiddleware的做用是在過程當中間獲得一個新的、比較複雜的Id進行一系列處理,可是最後輸出的給用戶看的表示結果仍是同樣的

相關文章
相關標籤/搜索
本站公眾號
   歡迎關注本站公眾號,獲取更多信息