UNPKG

@ng1005/chrome-extension-common

Version:

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

244 lines (236 loc) 7.34 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, isString } from "../utils/Utils"; class StorageDataService extends EventBusDemo implements IStorageInterface{ script:string='content'; data:KeyValue={} keys:KeyValue={ get:'_message_storage_data_service_get', set:'_message_storage_data_service_set', watch:'_message_storage_data_service_watch', listener:'_message_storage_data_service_listener', } watchKeys:Array<string>=[]//具体要监听的字段 $runtimeBus:RuntimeEventBus=$bus; constructor(script?:string){ super() let defaultScript='content' if(isBackgroundScript()){ defaultScript='background' }else if(isPopupScript()){ defaultScript='popup' } this.script=script||defaultScript;//当前脚本 // this.$runtimeBus=new RuntimeEventBus() 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(sendResponse) }else{ res=handler[i].call(_this, oldVal,newVal,sender,sendResponse) if(res){ sendResponse(res)//发送返回值来实现$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(sendResponse) }else{ res=handler.call(_this,oldVal,newVal,sender,sendResponse) if(res){ sendResponse(res)//发送返回值来实现$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)=>{ let result:KeyValue={} if(isString(name)){ result[<string>name]=this.data[<string>name] resolve(result) }else if(Array.isArray(name)){ name.forEach((key)=>{ result[key]=this.data[key] }) resolve(result); }else{ reject('error name') } }) } /** * 设置数据 * @param {*} name * @param {*} value */ set(name:string|Object,value?:any){ 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((resolve,reject)=>{ let data:KeyValue={} if(isString(name)){ data[<string>name]=value this.checkWatch(data) this.data[<string>name]=value; }else if(isObject(name)){ data=<KeyValue>name this.checkWatch(data) this.data=Object.assign(this.data,name) }else{ reject('name error') } resolve(true) }) } /** * 检查本次更新是否有需要监听的字短 * @param data */ async checkWatch(data:KeyValue){ let keys=Object.keys(data) let _this=this; this.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 StorageDataService