接口管理库NRequire.js

'use strict';
/*
异步数据模块加载器
功能
1、加载器存在 主任务、副任务、子任务
newRequire 表示加载主任务,主任务并发执行,newRequire(param1),执行主任务的时候,暂停副任务,主任务结束后,再执行副任务。
runFreeRequest 表示加载副任务,任务放队列,主任务结束后,副任务按顺序执行
require表示加载子任务,rule匹配后,执行ruleFunc(param1)

2、执行过程为:传入数据模块,匹配rule,执行ruleFunc,返回结果
param1表示模块数据,可为 String、Object、Number、Array,
onRequest表示定义规则,onRequest(rule,ruleFunc)
rule表示模块规则,可为 String、Function、Number,匹配param1则返回true,然后运行规则函数
ruleFunc表示规则函数,可为AsyncFunction、Function,返回结果

3、生命周期
相同的param1在同一个newRequire周期中,只会加载一次,默认缓存时间为0,也就是在下一个newRequire之前会被清理调缓存。

4、设置param1缓存时间
onRequest(rule,ruleFunc,0) 定义符合规则的所有模块,无缓存,优先级底
this.setCacheTime(param1,1000) 在ruleFunc函数内调用,设置缓存1秒,优先级高

demo
//主进程加载器
const mainLoader=new AMDLoader();
mainLoader.defineArr();//数组规则
mainLoader.defineObj();//对象规则

//定义method模块规则
const onRequest=mainLoader.onRequest.bind(mainLoader);
onRequest(function (param1) {
    if(this.isType(param1,'Object')&&param1.method){
        const key=JSON.stringify(param1);
        if(key.length>200){
            return cryptoPassFunc(key)
        }
        return true;
    }
},async function (param1) {
    const func=methodMap[param1.method]||getMethod(param1.method);
    if(func){
        return await func.call(this,param1);
    }else{
        throw 'method不存在';
    }
},300000);//设置method缓存时间5分钟

主任务
mainLoader.newRequire([
    {
        method:'random',
        needFlag:true,
        t:1
    },
    {
        method:'random',
    }
]).then(function (res) {
    console.log(res)
}).catch(function (e) {
    console.log(e)
})

=》[ { flag: 'S',
    startTime: 1585545204173,
    data: 1585545204475,
    endTime: 1585545204475 },
  1585545204777 ]

副任务
mainLoader.runFreeRequest({
    method:'task1',
}).then(function (res) {
    console.log(res)
}).catch(function (e) {
    console.log(e)
})

=》完成任务 [ 'task1:1585547219188', 'clearMoreCache:59' ]
*/
//主任务
class NRequire {
    isType(obj,str){
        return Object.prototype.toString.call(obj) === '[object '+str+']';
    }
    constructor(loader){
        this.loader=loader;
        this.cacheMap={};//缓存
        this.startTimeMap={};
        this.endTimeMap={};

        //获取没过期的缓存
        const time=new Date().getTime();
        for(let url in loader.cacheMap){
            if(this.isType(loader.moduleCacheTime[url],'Number')&&time<loader.endTimeMap[url]+loader.moduleCacheTime[url]){
                this.cacheMap[url]=loader.cacheMap[url];
            }else{
                delete loader.moduleCacheTime[url];
                loader.clearCache(url)
            }
        }
    }
    //加载模块
    async require(param1){

        //是否匹配到规则
        const {key,index}=this.loader.matchRule(param1);
        //需要缓存
        if(index>-1){
            let res;
            const rulFunc=this.loader.ruleFuncs[index];
            const rulTime=this.loader.ruleCacheTimes[index];

            //匹配缓存,同时缓存在有效期
            if(typeof this.cacheMap[key]!=='undefined'){
                return this.cacheMap[key];
            }

            if(this.isType(rulTime,'Number')){
                this.loader.moduleCacheTime[key]=rulTime;
            }
            if(this.isType(rulFunc,'AsyncFunction')){
                res=await this.loader.startKey(key);
                if(!res){
                    this.startTimeMap[key]=new Date().getTime();
                    try {
                        res=await rulFunc.call(this,param1);
                    }catch (e) {
                        this.loader.endKey(key,res)
                        throw e;
                    }
                    this.cacheMap[key] = res;
                    //缓存时间
                    this.endTimeMap[key]=new Date().getTime();
                }
                this.loader.endKey(key,res)
            }else if(this.isType(rulFunc,'Function')){
                res=rulFunc.call(this,param1);
                this.cacheMap[key] = res;
            }else{
                res=rulFunc;
                this.cacheMap[key] = res;
            }
            //缓存放入loader中
            if(this.loader.moduleCacheTime[key]>0){
                this.loader.cacheMap[key]=res;
                this.loader.startTimeMap[key]=this.startTimeMap[key];
                this.loader.endTimeMap[key]=this.endTimeMap[key];
            }
            return res;
        }else{
            return param1;
        }
    }
    //设置模块缓存时间
    setCacheTime(param1,cacheTime){
        const item=this.loader.matchRule(param1);
        if(this.isType(cacheTime,'Number')){
            this.loader.moduleCacheTime[item.key]=cacheTime;
        }
    }
}

//AMD模块缓存加载器
class AMDLoader{
    //设置模块缓存时间
    setCacheTime(param1,cacheTime){
        const item=this.matchRule(param1);
        if(this.isType(cacheTime,'Number')){
            this.moduleCacheTime[item.key]=cacheTime;
        }
    }
    isType(obj,str){
        return Object.prototype.toString.call(obj) === '[object '+str+']';
    }
    async startKey(key){
        this.willI[key]=this.willI[key]||0;
        this.curI[key]=this.curI[key]||0;
        this.willI[key]++;
        if(this.willI[key]>this.curI[key]+1){
            return await new Promise((res)=> {
                this.loadBack[''+key+this.willI[key]]=res;
            })
        }
    }
    endKey(key,res){
        if(this.curI[key]<this.willI[key]){
            this.curI[key]++;
            while (this.curI[key]<this.willI[key]){
                this.curI[key]++;
                this.loadBack[''+key+this.curI[key]](res);
                delete this.loadBack[''+key+this.curI[key]];
            }
        }

    }
    constructor(){
        //配置
        this.rules=[];
        this.ruleFuncs=[];
        this.ruleCacheTimes=[];

        this.cacheMap={};//永久缓存,最大100
        this.moduleCacheTime={};//临时缓存时间
        this.startTimeMap={};
        this.endTimeMap={};
        this.nearTimeMap={};

        //异步工具
        this.willI={};
        this.curI={};
        this.loadBack={};

        this.running=0;
        this.actionArr=[];

    }
    //主任务
    async newRequire(param1){
        this.running++;
        const nQest=new NRequire(this);//主任务
        try {
            const res=await nQest.require(param1);
            this.running--;
            return res;
        }catch (e) {
            let obj=this.isType(e,'Object')&&e.logType==='_error'?e:{
                msg:e,
                logType:'error',
                bizData:param1,
            };
            this.running--;
            if(this.running===0){
                //执行副任务
                this.runFreeRequest()
            }
            //内部错误
            // this.log(obj)
            throw obj.msg;
        }
    }
    //副任务
    async runFreeRequest(param1){
        if(param1){
            this.actionArr.push(param1);
        }

        if(this.running>0){
            console.log('存在主任务');
            return []
        }

        const arr=[]
        while (this.running===0&&this.actionArr.length>0){
            const bizData=this.actionArr.shift();
            const nQest=new NRequire(this);//主任务
            try {
                const res=await nQest.require(bizData)
                arr.push(res);
            }catch (e) {
                arr.push(e);
            }
        }
        return arr
    }

    clearCache(key){
        delete this.cacheMap[key];
        delete this.nearTimeMap[key];
        delete this.startTimeMap[key];
        delete this.endTimeMap[key];
    }
    onRequest(rule,ruleFunc,cacheTime){
        this.rules.push(rule);
        this.ruleFuncs.push(ruleFunc);
        this.ruleCacheTimes.push(cacheTime);
    }
    //命中规则
    matchRule(param1){
        let key;//key必然是个字符或者数字
        if(this.isType(param1,'String')){
            key=param1
        }else if(this.isType(param1,'Object')){
            key=JSON.stringify(param1)
        }else if(this.isType(param1,'Array')){
            key=JSON.stringify(param1)
        }else if(this.isType(param1,'Number')){
            key=JSON.stringify(param1)
        }

        let index=-1;
        let keyback;//params 返回值
        for(let i=this.rules.length-1;i>-1;i--){
            const rule=this.rules[i];
            if(this.isType(rule,'Function')){
                keyback=rule.call(this,param1);
                if(keyback){
                    index=i;
                    break;
                }
            }else if(this.isType(rule,'String')||this.isType(rule,'Number')){
                keyback=rule;
                if(param1===rule){
                    index=i;
                    break;
                }
            }
        }
        if(index>-1){
            if(this.isType(keyback,'String')){
                key=keyback;
            }
        }
        return {
            index:index,
            key:key,
            keyback:keyback,
        }

    }

    log(obj){
        console.log('发邮件',obj)
        if(obj.logType==='_error'){

        }else if(obj.logType==='error'){

        }
    }

    //定义数组加载,[name1,name2]
    defineArr(){
        this.onRequest(function (param1) {
            if(this.isType(param1,'Array')){
                return true;
            }
        },async function (param1) {
            const arr1=[]
            for(let i=0;i<param1.length;i++){
                const res=await this.require(param1[i])
                arr1.push(res)
            }
            return arr1
        })
    }
    //定义对象加载 {name1:'name1',name2:'name2'}
    defineObj(){
        this.onRequest(function (param1) {
            if(this.isType(param1,'Object')){
                return true;
            }
        },async function (param1) {
            const nobj={};
            const arr1=[]
            const arr2=[]
            for(let k in param1){
                arr1.push(k);
                arr2.push(this.require(param1[k]));
            }
            const arr3=await Promise.all(arr2);
            for(let i=0;i<arr1.length;i++){
                nobj[arr1[i]]=arr3[i];
            }
            return nobj
        })
    }

}

module.exports=AMDLoader;

 

posted @ 2020-07-15 17:17  无工时代  阅读(181)  评论(0编辑  收藏  举报