博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
MetaMask/obs-store
阅读量:6835 次
发布时间:2019-06-26

本文共 8511 字,大约阅读时间需要 28 分钟。

https://github.com/MetaMask/obs-store

ObservableStore

ObservableStore is a synchronous in-memory store for a single value, that you can subscribe to updates on

ObservableStore是一个内存中的可以订阅更新的同步存储,只存储一个值

const store = new ObservableStore(initState)store.subscribe(function showValue(value) {  console.log('saw value:', value)}) //通过调用putState()来存储值store.putState(5) // "saw value: 5" ,存储了5store.putState(true) // "saw value: true" ,true覆盖了之前的5的值store.putState({ hello: 'world' }) // "saw value: { hello: 'world' }" ,{ hello: 'world' }覆盖了之前的true的值console.log(store.getState().hello) // "world" ,通过调用getState()函数来得到存储的值
从上面的例子可以看出能且只能够存储一个值

streams

Each ObservableStore can be turned into an ObservableStoreStream. An ObservableStoreStream is a duplex stream that you can pipe new values into it or pipe its updated values out of it.

ObservableStore可以转换成ObservableStoreStream流,并且是一个双工流

Special behavior: Doesnt buffer outgoing updates, writes latest state to dest on pipe.

不缓冲输出更新,将最新状态写到管道dest上

const pipe = require('pump')const asStream = require('obs-store/lib/asStream')const storeOne = new ObservableStore(initState)const storeTwo = new ObservableStore()pipe(//相当于asStream(storeOne).pipe(transformStream).pipe(asStream(storeTwo)),而且使用pump监听错误  asStream(storeOne),  transformStream,  asStream(storeTwo))

 

Changelog

3.0.0

ObservableStore are no longer streams. You can create streams via asStream.

通过asStream来创建ObservableStoreStream

/index.js

'use strict'const extend = require('xtend')const EventEmitter = require('events')class ObservableStore extends EventEmitter {  constructor (initState = {}) {    super()    // set init state    this._state = initState  }  // wrapper around internal getState  getState () {//输出值    return this._getState()  }    // wrapper around internal putState  putState (newState) {    this._putState(newState)//存储newState值    this.emit('update', newState)//并触发subscribe中的'update'事件,并调用相应的handler函数  }  updateState (partialState) {//更改里面的一部分的值    // if non-null object, merge    if (partialState && typeof partialState === 'object') {      const state = this.getState()      const newState = Object.assign({}, state, partialState)      this.putState(newState)    // if not object, use new value    } else {      this.putState(partialState)    }  }  // subscribe to changes  subscribe (handler) {    this.on('update', handler)  }  // unsubscribe to changes  unsubscribe (handler) {    this.removeListener('update', handler)//移除'update'事件  }  //  // private  //  // read from persistence  _getState () {    return this._state  }  // write to persistence  _putState (newState) {    this._state = newState  }}module.exports = ObservableStore

 

其调用的lib库:

//asStream.js

作用是将ObsStore转成ObsStoreStream流,并定义流相应的一些方法

const DuplexStream = require('stream').Duplexmodule.exports = asStreamfunction asStream(obsStore) {  return new ObsStoreStream(obsStore)}////////class ObsStoreStream extends DuplexStream {  constructor(obsStore) {    super({      // pass values, not serializations      objectMode: true,    })    // dont buffer outgoing updates    this.resume()    // save handler so we can unsubscribe later    this.handler = (state) => this.push(state)    // subscribe to obsStore changes    this.obsStore = obsStore    this.obsStore.subscribe(this.handler)  }  // emit current state on new destination  pipe (dest, options) {//调用pipe函数,将obsStore.getState()值传到dest    const result = DuplexStream.prototype.pipe.call(this, dest, options)    dest.write(this.obsStore.getState())    return result  }  // write from incomming stream to state  _write (chunk, encoding, callback) {    this.obsStore.putState(chunk)    callback()  }  // noop - outgoing stream is asking us if we have data we arent giving it  _read (size) { }  // unsubscribe from event emitter  _destroy (err, callback) {    this.obsStore.unsubscribe(this.handler);    super._destroy(err, callback)  }}

 

//localStorage.js

设置一个继承ObservableStoreLocalStorageStore,页面端的global.localStorage就是这个

'use strict'const ObservableStore = require('../')class LocalStorageStore extends ObservableStore {  constructor (opts = {}) {    if (!global.localStorage) throw new Error('LocalStorageStore - can\'t find localStorage.')//global.localStorage即浏览器本身是否有本地存储    super()    this._storageKey = opts.storageKey    if (!this._storageKey) throw new Error('LocalStorageStore - no storageKey specified.')  }  //  // private  //  // read from persistence  _getState () {    const serialized = global.localStorage.getItem(this._storageKey)//不同的_storageKey对应的是本地存储的不同内容    return serialized ? JSON.parse(serialized) : undefined  }  // write to persistence  _putState (newState) {    const serialized = JSON.stringify(newState)    return global.localStorage.setItem(this._storageKey, serialized)  }}module.exports = LocalStorageStore

还有一些别的,但是先不管,之后用到再说

 

 

测试:

 

'use strict'const test = require('tape')const pipe = streamUtils.pipeconst ObservableStore = require('../')const asStream = require('../lib/asStream')const TEST_WAIT = 200test('basic stream', function(t){  t.plan(2)  const initState = 'init'  const nextState = 'next'  const storeOne = new ObservableStore(initState)//在初始化时就存储值initState  const storeTwo = new ObservableStore()//在初始化时并没有存储值  storeTwo.once('update', (value) => {//监听一次'update'事件    initValueCheck(value)//查看value值与initState值是否相同    storeTwo.once('update', nextValueCheck)//再监听一次查看与nextState的值是否相同  })  pipe(//将storeOne流中的值initState传给storeTwo流,storeTwo调用putState时会调用一次'update'事件,查看是否于initState值相同    asStream(storeOne),    asStream(storeTwo)  )  storeOne.putState(nextState)//将storeOne中的值从initState改变成nextState,这里又会触发一次'update'事件,这次是查看是否于nextState相同  function initValueCheck(value){    t.equal(value, initState, 'storeTwo subscribed: state is initState')  }  function nextValueCheck(value){    t.equal(value, nextState, 'storeTwo subscribed: state is nextState')  }})test('double stream', function(t){  t.plan(4)  const initState = 'init'  const nextState = 'next'  const storeOne = new ObservableStore(initState)  const storeTwo = new ObservableStore()  storeTwo.once('update', (initValue) => {    initValueCheck('storeTwo', initValue)    storeTwo.once('update', (nextValue) => nextValueCheck('storeTwo', nextValue))  })  const storeThree = new ObservableStore()  storeThree.once('update', (initValue) => {    initValueCheck('storeThree', initValue)    storeThree.once('update', (nextValue) => nextValueCheck('storeThree', nextValue))  })  pipe(    asStream(storeOne),    asStream(storeTwo)//storeTwo触发一次'update'  )  pipe(    asStream(storeOne),    asStream(storeThree)//storeThree触发一次'update'  )  storeOne.putState(nextState)//将会导致storeTwo、storeThree再分别触发一次  function initValueCheck(label, value){    t.equal(value, initState, `${label} subscribed: state is initState`)  }  function nextValueCheck(label, value){    t.equal(value, nextState, `${label} subscribed: state is nextState`)  }})

 

 

LocalStorageStore的测试,首先localStorage是定义好的,并且是有storageKey值的,如{ storageKey: 'test' }

'use strict'const test = require('tape')const LocalStorageStore = require('../lib/localStorage')test('localStorage - localStorage presence validation', function(t){  t.plan(2)  t.notOk(global.localStorage, 'global.localStorage not defined')  t.throws(() => {    new LocalStorageStore({ storageKey: 'test' })  }, Error, 'throws error when localStorage is not defined')})test('localStorage - storageKey validation', function(t){  t.plan(2)  global.localStorage = createLocalStorage()  t.ok(global.localStorage, 'global.localStorage is defined')  t.throws(() => {    new LocalStorageStore()  }, Error, 'throws error when opts.storageKey is not defined')})test('localStorage - basic test', function(t){  t.plan(2)  global.localStorage = createLocalStorage()  t.ok(global.localStorage, 'global.localStorage is defined')  const store = new LocalStorageStore({ storageKey: 'test' })  store.putState(42)  t.equal(store.getState(), 42, 'store works roundtrips values great')})test('localStorage - obj test', function(t){  t.plan(2)  global.localStorage = createLocalStorage()  t.ok(global.localStorage, 'global.localStorage is defined')  const store = new LocalStorageStore({ storageKey: 'test' })  store.putState({ a: 123 })  t.deepEqual(store.getState(), { a: 123 }, 'store works roundtrips obj values great')})function createLocalStorage() {  const values = {}  const localStorage = {}  localStorage.getItem = (key) => values[key]  localStorage.setItem = (key, value) => values[key] = value  return localStorage}

 

转载于:https://www.cnblogs.com/wanghui-garcia/p/9885458.html

你可能感兴趣的文章
Scrapy-redis分布式组件
查看>>
package.json里的一些属性讲解
查看>>
leetcode 12 Integer to Roman
查看>>
Swoole+Lumen:同步编程风格调用MySQL异步查询
查看>>
探索 JUC 之美---Future 与 FutureTask
查看>>
《Java RESTful Web Service实战》第一章的实现补漏
查看>>
Linux 下统计文件夹大小及文件数量
查看>>
pgbackrest 简要使用说明
查看>>
Struts知识问答
查看>>
C# 中符号的作用[备忘]
查看>>
关于preempt_enable 和 preempt_disable 【转】
查看>>
SQLAlchemy 与 fask-SQLAlchemy 中的多表查询例子
查看>>
JS 获取图片原始尺寸-防止图片溢出
查看>>
Java反射
查看>>
Codeforce 712A Memory and Crow
查看>>
Keil代码中for循环延时问题
查看>>
JAX-RS(基于Jersey) + Spring 4.x + MyBatis构建REST服务架构
查看>>
ArcGIS制图之Subset工具点抽稀
查看>>
很好看的后台管理界面
查看>>
Maven 使用Eclipse构建Web项目
查看>>