• AMDLoader数据模块加载器


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

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

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

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

    demo
    主任务
    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.onRequireFree({
    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) {
    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{
    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.onRequireFree()
    }
    //内部错误
    // this.log(obj)
    throw obj.msg;
    }
    }
    //副任务
    async onRequireFree(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];
    }
    defineRule(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.defineRule(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.defineRule(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;
  • 相关阅读:
    使用Bat自动打包并通过FTP发送到备份服务器——实战测试
    什么是STP
    【基础】华为单臂路由技术配置记录
    Windows Server 2012系统上安装.net framework3.5教程
    eNSP启动设备AR1失败记一次解决步骤
    Linux系统设置 SSH 通过密钥登录
    windows和linux修改ipv6和ipv4的优先级
    思科交换机配置中继
    【Nginx】Nginx反向代理转发Host设置
    idea查看类的uml图
  • 原文地址:https://www.cnblogs.com/caoke/p/12567075.html
Copyright © 2020-2023  润新知