分享web开发知识

注册/登录|最近发布|今日推荐

主页 IT知识网页技术软件开发前端开发代码编程运营维护技术分享教程案例
当前位置:首页 > 运营维护

MetaMask/obs-store

发布时间:2023-09-06 02:21责任编辑:胡小海关键词:暂无标签

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

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)//存储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库:

obs-store/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) ?}}

obs-store/lib/localStorage.js

设置一个继承ObservableStore的LocalStorageStore,页面端的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}

MetaMask/obs-store

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

知识推荐

我的编程学习网——分享web前端后端开发技术知识。 垃圾信息处理邮箱 tousu563@163.com 网站地图
icp备案号 闽ICP备2023006418号-8 不良信息举报平台 互联网安全管理备案 Copyright 2023 www.wodecom.cn All Rights Reserved