UNPKG

@ng1005/chrome-extension-common

Version:

chrome扩展通用库--消息与storage

277 lines (273 loc) 9.53 kB
import {EventBusDemo} from "../message/EventBusDemo"; import IStorageInterface from "../interface/IStorageInterface"; import $bus,{RuntimeEventBus} from "../message/RuntimeEventBus"; import { KeyValue } from "../types/KeyValue"; import ResponseUtils from "../utils/ResponseUtils"; import { isArray, isBackgroundScript, isFunctionAsync, isObject, isPopupScript, isPromise, isString } from "../utils/Utils"; class StorageDefaultService extends EventBusDemo implements IStorageInterface{ script: string='content'; _keys: KeyValue={ local:{get:'_message_storage_local_service_get',set:'_message_storage_local_service_set',watch:'_message_storage_local_service_watch',listener:'_message_storage_local_service_listener'}, managed:{get:'_message_storage_managed_service_get',set:'_message_storage_managed_service_set',watch:'_message_storage_managed_service_watch',listener:'_message_storage_managed_service_listener',}, session:{get:'_message_storage_session_service_get',set:'_message_storage_session_service_set',watch:'_message_storage_session_service_watch',listener:'_message_storage_session_service_listener',}, sync:{get:'_message_storage_sync_service_get',set:'_message_storage_sync_service_set',watch:'_message_storage_sync_service_watch',listener:'_message_storage_sync_service_listener',}, }; keys:KeyValue={} type:string='local' $runtimeBus:RuntimeEventBus=$bus chromeVars:KeyValue={ local:chrome.storage.local, managed:chrome.storage.managed, session:chrome.storage.session, sync: chrome.storage.sync } watchKeys:Array<string>=[]//具体要监听的字段 _events:Map<string,Function|Array<Function>>; chromeVar:any constructor(type?:string,script?:string){ super() let defaultScript='content' if(isBackgroundScript()){ defaultScript='background' }else if(isPopupScript()){ defaultScript='popup' } this._events = new Map(); // 存储事件/回调键值对 this.type=type||'local' this.type=this._keys[this.type]?this.type:'local'//默认没有的时候就使用local this.keys=this._keys[this.type] this.chromeVar=this.chromeVars[this.type] this.script=script||defaultScript;//当前脚本 if(this.script==='background'){ this.listener() } this.listenerWatch() } /** * 重写方法 * @param name * @param callback * @returns */ $on(name: string, callback: Function):this { if(!name)return this; if(this.script==='background'){ if(isString(name)){ this.watchKeys.push(name) } return this; } this.$runtimeBus.$emitBackground(this.keys.watch,name) super.$on(name,callback); return this; } /** * 重写提交事件 * @param type 消息类型 * @param args 参数 * @returns */ $emit(type:string, ...args:any):Promise<any>{ const [oldVal,newVal]=args; if(!type){ Promise.reject('错误字段') } if(this.script==='background'){ const data={key:type,oldVal,newVal} this.$runtimeBus.$emitAllTabs(this.keys.listener,data) } return Promise.resolve('') } listenerWatch(){ let _this=this; if(this.script==='background'){//后台监听其他页面提交过来的需要监听的key //仅支持每次监听一个key this.$runtimeBus.$on(this.keys.watch,(data:any,sender:chrome.runtime.MessageSender,sendResponse:any)=>{ if(isString(data)){ _this.watchKeys.push(data) } return true; }) }else{//非background页面 this.$runtimeBus.$on(this.keys.listener,(data:any,sender:chrome.runtime.MessageSender,sendResponse:any)=>{ // console.log('addListener----',request,sender,sendResponse) //data:{key:监听字段,old:any,new:any} return new Promise((resolve,reject)=>{ _this.handler(data,sender,sendResponse).then((res)=>{ resolve(res) }).catch((err:any)=>{ reject(err||'监听失败') }) }) }) } } /** * 消息处理 * @param {*} request:any * @param {*} sender:chrome.runtime.MessageSender * @param {*} sendResponse:any */ async handler(data:any,sender:chrome.runtime.MessageSender,sendResponse:any){ let _this=this; //data:{key:监听字段,old:any,new:any} // console.log('listener------',data) const {key,oldVal,newVal}=data; if(!key){ return; } let handler = _this._events.get(key)//所有该类型的函数集合 if(!handler)return;//无任何监听则退出 if (Array.isArray(handler)) { // 是数组,说明有多个监听者,需要依次触发里边的函数 for (let i = 0; i < handler.length; ++i) { let res:any='' if(isFunctionAsync(handler)){ handler[i].call(_this, oldVal,newVal,sender,sendResponse).then((data:any)=>{ sendResponse(ResponseUtils.success(data)) }).catch((e:any)=>{ sendResponse(ResponseUtils.error(e))//默认发送 }) }else{ res=handler[i].call(_this, oldVal,newVal,sender,sendResponse) if(isPromise(res)){ res.then((r:any)=>{ sendResponse(ResponseUtils.success(r)) }).catch((e:any)=>{ sendResponse(ResponseUtils.error(e))//默认发送 }) }else if(res){ sendResponse(ResponseUtils.success(res))//发送返回值来实现$emit中Promise返回内容 }else{ sendResponse(ResponseUtils.error('未知错误'))//发送返回值来实现$emit中Promise返回内容 } } } } else { // 单个函数的情况直接触发即可 // let res=await handler.call(_this, ...args,sender,sendResponse) let res:any='' if(isFunctionAsync(handler)){ handler.call(_this, oldVal,newVal,sender,sendResponse).then((data:any)=>{ sendResponse(ResponseUtils.success(data)) }).catch((e:any)=>{ sendResponse(ResponseUtils.error(e))//默认发送 }) }else{ res=handler.call(_this,oldVal,newVal,sender,sendResponse) if(isPromise(res)){ res.then((r:any)=>{ sendResponse(ResponseUtils.success(r)) }).catch((e:any)=>{ sendResponse(ResponseUtils.error(e))//默认发送 }) }else if(res){ sendResponse(ResponseUtils.success(res))//发送返回值来实现$emit中Promise返回内容 }else{ sendResponse(ResponseUtils.error('未知错误'))//发送返回值来实现$emit中Promise返回内容 } } } } listener(){ let _this=this; this.$runtimeBus.$on(this.keys.get,(data:any,sender:chrome.runtime.MessageSender,sendResponse:any)=>{ return new Promise((resolve,reject)=>{ _this.get(data).then((res)=>{ resolve(res) }).catch((err:any)=>{ reject(err||'获取失败') }) }) }) this.$runtimeBus.$on(this.keys.set,(data:any,sender:chrome.runtime.MessageSender,sendResponse:any)=>{ return new Promise((resolve,reject)=>{ if(!isObject(data)){ reject('设置失败,data不是对象'); return } _this.set(data).then((res)=>{ resolve(res) }).catch((err:any)=>{ reject(err||'设置失败') }) }) }) } /** * 根据key获取数据 * @param {*} name */ get(name:string|Array<string>){ if(this.script!=='background'){ return this.$runtimeBus.$emitBackground(this.keys.get,name) } return new Promise((resolve,reject)=>{ if(isString(name)||isArray(name)){ this.chromeVar.get(name).then((data:any) => { resolve(data) }).catch((e:any)=>{ reject(e.message||'未知异常') }) }else{ reject('error name') } }) } /** * 设置数据 * @param {*} name * @param {*} value */ set(name:string|Object,value?:any){ if(!name){ Promise.reject('错误的字段') } if(this.script!=='background'){ let data:KeyValue={} if(isObject(name)){ data=<KeyValue>name; }else{ data[<string>name]=value; } return this.$runtimeBus.$emitBackground(this.keys.set,data) } return new Promise(async(resolve,reject)=>{ let data:KeyValue={} if(isObject(name)){ data=<KeyValue>name }else{ data[<string>name]=value; } let _this=this; _this.checkWatch(data) this.chromeVar.set(data).then(() => { resolve(true) }).catch((e:any)=>{ reject(e.message||'未知异常') }) }) } /** * 检查本次更新是否有需要监听的字短 * @param data */ async checkWatch(data:KeyValue){ let keys=Object.keys(data) let _this=this; this.chromeVar.get(keys).then((res:KeyValue) => { for(let i=0;i<keys.length;i++){ const key=keys[i] if(_this.watchKeys.includes(key)){//在监听里面 //判断是否有变化 if(JSON.stringify(data[key])!=JSON.stringify(res[key])){//变更 _this.$runtimeBus.$emitAllTabs(_this.keys.listener,{key,oldVal:data[key],newVal:res[key]}) } } } }).catch((e:any)=>{ Promise.reject(e.message||'未知异常') }) } } export default StorageDefaultService