码迷,mamicode.com
首页 > Web开发 > 详细

MetaMask/obs-store

时间:2018-11-07 17:12:53      阅读:146      评论:0      收藏:0      [点我收藏+]

标签:parse   3.0.0   git   util   around   hunk   his   mod   exp   

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" ,存储了5 store.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

obs-store/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)//存储newStatethis.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库:

obs-store/lib/asStream.js

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

const DuplexStream = require(stream).Duplex

module.exports = asStream


function 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)
  }

}

 

obs-store/lib/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 = 200


test(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)//将会导致storeTwostoreThree再分别触发一次

  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
}

 

MetaMask/obs-store

标签:parse   3.0.0   git   util   around   hunk   his   mod   exp   

原文地址:https://www.cnblogs.com/wanghui-garcia/p/9885458.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!