@ng1005/chrome-extension-common
Version:
chrome扩展通用库--消息与storage
277 lines (273 loc) • 9.53 kB
text/typescript
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