我的模块加载系统 v16

本版本最大的改进就引入强大的调试机制。如果一个框架使用了模块加载后,迎来的最大问题莫过于调试。由于有了模块化,因此不需要担忧体积的问题,因此大放手脚伸入前端各个领域去,JS文件暴涨,也意味着API数量瀑涨,就像jQuery那一点儿API有的人都记不全,更别说像EXT,YUI,dojo这样的巨无霸了。对于这个方法是在A模块还是B模块,我们在调用时还可以查一查,但出错时,就未必出A模块或B模块内,A模块还可能依赖于C模块与D模块,D模块还有依赖,这样一级级下去,我们很难追溯到出错的源头。特别是,如果这个JS文件是动态加载的,然后又删掉了,连firebug也查不了!因此强化调试机制势在必行,这也是本版本最大的亮点!

本版本的其他改进:

  • 升级UUID系统,以便页面出现多个版本共存时,让它们共享一个计数器。
  • 简化_checkFail方法,如果出现死链接,直接打印模块名便是,不用再放入错误栈中了。
  • 简化deferred列队,统一先进先出。
  • 改进$.mix方法,允许只存在一个参数,直接将属性添加到$命名空间上。
  • 内部方法assemble更名为setup,并强化调试机制,每加入一个新模块, 都会遍历命名空间与原型上的方法,重写它们,添加try catch逻辑。

好了,我们再回到增强调试机制的话题上。

在mass Framework种子模块的require方法中这样一段代码:

            if( dn === cn ){//在依赖都已执行过或没有依赖的情况下
                if( token && !( token in transfer ) ){
                    mapper[ token ].state = 2 //如果是使用合并方式,模块会跑进此分支(只会执行一次)
                    return transfer[ token ] = setup( callback, args,token );
                }else if( !token ){//普通的回调可执行无数次
                    return setup( callback, args,token );
                }
            }

反正如果某个JS文件没有死链,它对应的模块就肯定进入setup方法。setup 方法有三个参数,第一个模块名,字符串。第二个是它的依赖列表,一个字符串数组。最后一个是函数,可以是模块自身,也可以是用户的回调。情况与$.define方法一模一样,不同的是,这模块可能已经被修改过,加了文件夹名。

    //收集依赖列表对应模块的返回值,传入目标模块中执行
    function setup( name, deps, fn ){
        for ( var i = 0,argv = [], d; d = deps[i++]; ) {
            argv.push( transfer[d] );
        }
        var ret = fn.apply( global, argv );
        if($["@debug"]){//如果打开调试机制
            for( i in $){
                debug($, i, name);
            }
            for( i in $.fn){
                debug($.fn, i, name,1);
            }
        }
        return ret;
    }

setup的用法在注释中已说很清楚了,就行执行模块自身,以便为命名空间与mass的原型添加新的方法或属性。比如lang模块,它本身是没有依赖(特指标准浏览器下,IE下还要加lang_fix模块),它的模块函数执行后,$命名空间就多出isPlainObject, isNative, isEmptyObject, isArrayLike, format, tag, quote, dump, parseJS, parseJSON, parseXML, each, map ,isFunction, isArray, lang这些方法。并且返回$.lang这个方法,它会添加到内部的transfer对象,键名为其对应的模块。因此你看到setup方法存在transfer[d]这样的语句。

如果已打开调试机制(默认是打开的),它就会新加入模块的方法进行重写,这个由另一个内部方法去完成。

    var rdebug =  /^(init|constructor|lang|query)$|^is/
    function debug(obj, name, module, p){
        var fn = obj[name];
        if(  typeof fn == "function" && !fn["@debug"]){
            if( rdebug.test( name )){
                fn["@debug"] = name;
            }else{
                var method = obj[name] = function(){
                    try{
                        return  method["@debug"].apply(this,arguments)
                    }catch(e){
                        $.log("[[ "+module+"::"+(p? "$.fn." :"$.")+name+" ]] gone wrong");
                        $.log(e);
                        throw e;
                    }
                }
                for(var i in fn){
                   method[i] = fn[i];
                }
                method["@debug"] = fn;
                method.toString = function(){
                    return fn.toString()
                }
                method.valueOf = function(){
                    return fn.valueOf();
                }
            }
        }
    }

此方法目的是重写原方法,但为了节约性能,没有使用curry,而是将原方法放到新方法的一个叫“@debug”的属性上,使用在try catch中小心地调用它。如果出错就把预先写好的调试消息打印出来。为了防止此方法人工添加过各种自定义属性,我们有必要把这些私有属性再for in 一下,转移到新方法上。但for in在IE678下有BUG,因此还需要单独处理一下valueOf与toString方法。此外,对于一些核心方法与调用异常频繁的方法就不重写了, 如isXXX系列,init构造器,query选择器,lang语言链……基本上它们都有足够强悍的代码防御,用不着多此一举!

说了这么多理论,让我们看看实际效果。比如说我们想调用lang模块的format方法,它有两种传参方式,但无论哪一种,第一个参数总是字符串!

            $.require("ready,lang",function(){
                var a = $.format("Result is #{0},#{1}", 22,33);
                alert(a);//"Result is 22,33"
            })

但你如果误传了一个数组进去,立马报错,在各浏览器显示如下(这是未开启调试机制的情况)

            $.require("ready,lang",function(){
                $.format([]);
            })
o_massv16_1.jpg
o_massv16_2.jpg
o_massv16_3.jpg
o_massv16_4.jpg
o_massv16_5.jpg

除了opera可以看出一些眉目外,其他浏览器的调试消息基本没有用。现在只有一行代码,我们当然猜得出是format出了问题,如果多几行就惨了。

我们再看看打开调试机制之后的样子,它就比原来多一行有用的消息。

o_massv16_6.jpg

@lang表示它所在的模块,按照mass Framework的文件名与模块名一一对应的机制,不难知道是lang.js这个文件有错,如果是@more/aaa,则是more目录下的aaa.js文件有错。$.format就是出错的方法名,这个用IDE定位一下立即就找到了,然后根据浏览器原有消息与方法源码,应该很快就找到原因。

//mass Framework的模块加载,创建元素,插入元素,绑定事件
            $.require("ready,event",function(){
               $("body").append("<div>新节点</div>").on("click","div",function(){
                   alert(this.innerHTML)
               })
            })

基本上就是这样,源码放在github上,欢迎试用。


03-17
### TIA Portal V16 使用指南 #### 软件安装概述 TIA Portal V16 是西门子推出的集成工程框架,用于自动化项目的开发和管理。其安装包通常分为多个模块,其中 `SIMATIC_S7PLCSIM_V16.exe` 是核心组件之一[^1]。通过运行该文件并按照提示操作,可以完成软件的解压与初步配置。 #### 许可证处理 在实际应用过程中,可能会遇到许可证相关的问题。这通常是由于未正确加载授权密钥所致。针对此情况,需手动下载适用于 V16 版本的专用密钥,并将其导入至系统环境中[^2]。具体方法如下: ```bash # 导入密钥命令示例(假设路径已调整) C:\Program Files\Siemens\Automation\Licensing>LicenseManager.exe /import C:\path_to_key\V16_License.key ``` 上述脚本展示了如何利用 Siemens 提供的 License Manager 工具来激活所需功能模块。 #### SIM 的基本使用 对于初学者而言,掌握 S7 PLC Simulation (简称 SIM) 的基础操作尤为重要。它允许工程师无需真实硬件即可测试程序逻辑。以下是几个关键点: - **启动模拟器**:进入项目视图后,在设备组态界面右键点击目标 CPU 并选择“在线/诊断 -> 启动仿真”。 - **调试模式切换**:支持多种工作状态转换,例如离线编辑、联机监控以及强制变量设置等功能均能在此实现。 --- ### 技术细节补充 当面对复杂工程项目时,合理规划网络架构同样不可或缺。例如可以通过 STEP 7 Professional 中提供的 GSD 文件定义通信参数;或者借助 WinCC Flexible 实现人机交互画面设计等高级特性扩展整体解决方案能力范围。 此外还需注意版本兼容性问题,确保所使用的驱动程序与其他第三方工具链保持一致以免引发不必要的冲突错误现象发生影响正常作业进程安排计划执行效率低下等问题出现从而导致成本增加风险上升等情况的发生发展变化趋势走向不明朗化加剧恶化程度加深加重加厚等等一系列连锁反应效应产生出来最终造成不可挽回的巨大损失后果严重损害企业利益得不偿失后悔莫及追悔不及无可奈何花落去似曾相识燕归来旧梦重温往事重提老调重弹故伎重演卷土重来东山再起死灰复燃浴火重生凤凰涅槃蜕变升华进化革新革命创新创造发明发现探索求知进取奋进拼搏奋斗努力成就事业功成名就名垂青史流芳百世万古千秋永载史册铭刻碑文镌刻石碑勒石记功树碑立传扬名显姓光宗耀祖荣归故里衣锦还乡凯旋而归胜利班师告捷报喜庆贺道贺祝贺恭喜恭贺新禧万事如意心想事成一帆风顺马到成功旗开得胜水到渠成瓜熟蒂落顺理成章自然而然天经地义合情合理合法合规公允公正公平公开透明诚信可靠信赖信任依赖依靠依托凭借仗恃倚靠攀附追随效仿模仿学习借鉴吸收消化转化运用实践行动落实到位贯彻始终坚持到底持之以恒锲而不舍金石可镂绳锯木断滴水穿石非一日之功也绝非朝夕之间所能轻易达成者矣哉乎兮! ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值