zoukankan      html  css  js  c++  java
  • mass Framework在后端的核心模块

    mass Framework前后通吃,后端是基于node.js组建起来。后端与前端不一样,是依赖于node.js内置模块提供的一些API,因此前端那些依赖于浏览器提供的DOM API的模块无法复用。现在掐指一算,基本上核心模块上只有lang, flow能用得上,more则多一点,如random, pinyin, base64, uuid...

    node.js内置了模块加载机制,这与我在前端使用的API非常不一致,我就再把它包装一层。核心模块与前端的核心模块在其他方法也尽量保持一致,当然像domReady在后端就不需要,去掉。如类型判定,由于是V8引擎,支持ECMA262v5,因此可以写得精简。最大的不同是,DEBUG用到mass.log,它的第二个参数是表示格式化高亮。

    代码是暂时丢在这里,以后还要做各种扩展的!

    (function(){
        //后端部分 2011.12.4 by 司徒正美
        function mass(){}
        var
        version = 0.1,
        class2type = {
            "[object global]" : "Global" ,
            "null" : "Null" ,
            "NaN"  : "NaN"  ,
            "undefined" : "Undefined"
        },
        toString = class2type.toString;
        /**
         * 糅杂,为一个对象添加更多成员
         * @param {Object} target 目标对象
         * @param {Object} source 属性包
         * @return {Object} 目标对象
         */
        function mix(target, source){
            var args = [].slice.call(arguments), key,
            ride = typeof args[args.length - 1] == "boolean" ? args.pop() : true;
            target = target || {};
            for(var i = 1; source = args[i++];){
                for (key in source) {
                    if (ride || !(key in target)) {
                        target[key] = source[key];
                    }
                }
            }
            return target;
        }
        var rformat = /([\d\D]+?)<\/code>/ig;
        var formats = {
            bold     : [1, 22],
            italic    : [3, 23],
            underline : [4, 24],
            inverse   : [7, 27],
            strike    : [9, 29]
        };
        var colors = {};
        ['black', 'red', 'green', 'yellow', 'blue', 'magenta', 'cyan', 'white'].forEach(function(word,i){
            colors[word] = i
        });
        colors.gray = 99;
        function format (arr, str) {
            return '\x1b[' + arr[0] + 'm' + str + '\x1b[' + arr[1] + 'm';
        };
        mix(mass,{//为此版本的命名空间对象添加成员
            rword : /[^, ]+/g,
            v : version,
            "@debug" : true,
            root: process.cwd(),
            /**
             * 数组化
             * @param {ArrayLike} nodes 要处理的类数组对象
             * @param {Number} start 可选。要抽取的片断的起始下标。如果是负数,从后面取起
             * @param {Number} end 可选。规定从何处结束选取
             * @return {Array}
             */
            slice: function (nodes, start, end) {
                for(var i = 0,n = nodes.length, result = []; i < n; i++){
                    result[i] = nodes[i];
                }
                if (arguments.length > 1) {
                    return result.slice(start , (end || result.length));
                } else {
                    return result;
                }
            },
            /**
             * 用于取得数据的类型或判定数据的类型
             * @param {Any} obj 要检测的东西
             * @param {String} str 要比较的类型
             * @return {String|Boolean}
             */
            type : function (obj, str){
                var result = class2type[ (obj == null || obj !== obj )? obj : toString.call(obj) ] || "#";
                if( result.charAt(0) === "#"){
                    if(Buffer.isBuffer(obj)){
                        result = 'Buffer'; //返回构造器名字
                    }else{
                        result = toString.call(obj).slice(8,-1);
                    }
                }
                if(str){
                    return str === result;
                }
                return result;
            },
            /**
             * 用于调试
             * @param {String} s 要打印的内容
             * @param {Boolean} color 进行各种颜色的高亮,使用<code style="format:blod;color:red;background:green">
             * format的值可以为formats中五个之一或它们的组合(以空格隔开),背景色与字体色只能为colors之一
             */
            log:function (s, color){
                if(color){
                    s = s.replace(rformat,function(a,style,ret){
                        style.toLowerCase().split(";").forEach(function(arr){
                            arr = arr.split(":");
                            var type = arr[0].trim(),val = arr[1].trim();
                            switch(type){
                                case "format":
                                    val.replace(/\w+/g,function(word){
                                        if(formats[word]){
                                            ret = format(formats[word],ret)
                                        }
                                    });
                                    break;
                                case "background":
                                case "color":
                                    var array = type == "color" ? [30,39] : [40,49]
                                    if( colors[val]){
                                        array[0] += colors[val]
                                        ret = format(array,ret)
                                    }
                            }
                        });
                        return ret;
                    });
                }
                console.log(s);
            },
            /**
             * 生成键值统一的对象,用于高速化判定
             * @param {Array|String} array 如果是字符串,请用","或空格分开
             * @param {Number} val 可选,默认为1
             * @return {Object}
             */
            oneObject : function(array, val){
                if(typeof array == "string"){
                    array = array.match(mass.rword) || [];
                }
                var result = {},value = val !== void 0 ? val :1;
                for(var i=0,n=array.length;i < n;i++){
                    result[array[i]] = value;
                }
                return result;
            },
            mix:mix
        });
    
        mass.noop = mass.error = function(){};
        "Boolean,Number,String,Function,Array,Date,RegExp,Arguments".replace(mass.rword,function(name){
            class2type[ "[object " + name + "]" ] = name;
        });
    
        var
        rmodule = /([^(\s]+)\(?([^)]*)\)?/,
        names = [],//需要处理的模块名列表
        rets = {},//用于收集模块的返回值
        cbi = 1e4 ;//用于生成回调函数的名字
        var map = mass["@modules"] = {};
        //执行并移除所有依赖都具备的模块或回调
        function resolveCallbacks(){
            loop:
            for (var i = names.length,repeat, name; name = names[--i]; ) {
                var  obj = map[name], deps = obj.deps;
                for(var key in deps){
                    if(deps.hasOwnProperty(key) && map[key].state != 2 ){
                        continue loop;
                    }
                }
                //如果deps是空对象或者其依赖的模块的状态都是2
                if( obj.state != 2){
                    names.splice(i,1);//必须先移除再执行
                    var fn = obj.callback;
                    rets[fn._name] = fn.apply(null,incarnate(obj.args));//只收集模块的返回值
                    obj.state = 2;
                    repeat = true;
                }
            }
        repeat &&  resolveCallbacks();
        }
        function incarnate(args){//传入一组模块名,返回对应模块的返回值
            for(var i = 0,ret = [], name; name = args[i++];){
                ret.push(rets[name]);
            }
            return ret;
        }
        function deferred(){//一个简单的异步列队
            var list = [],self = function(fn){
                fn && fn.call && list.push(fn);
                return self;
            }
            self.method = "pop";
            self.fire = function(fn){
                while(fn = list[self.method]()){
                    fn();
                }
                return list.length ? self : self.complete();
            }
            self.complete = mass.noop;
            return self;
        }
    
        var nativeModules = mass.oneObject("assert,child_process,cluster,crypto,dgram,dns,"+
            "events,fs,http,https,net,os,path,querystring,readline,repl,tls,tty,url,util,vm,zlib")
        function useNativeRequire(name,url){
            var nick = name.slice(1);
            if(nativeModules[nick]){
                map[name].state = 2;
                rets[name] = require(nick);
                resolveCallbacks();
            }else{
                url = url  || mass.root+"/" + nick + ".js";
                try{
                    require(url);
                    resolveCallbacks()
                }catch(e){
                    mass.stack(Function('mass.log("\033[31m'+e+'\033[39m")'));
                    mass.stack.fire();//打印错误堆栈
                }
            }
        }
        mass.mix(mass,{
            stack : deferred(),
            define:function(name,deps,callback){//模块名,依赖列表,模块本身
                if(typeof deps == "function"){//处理只有两个参数的情况
                    callback = deps;
                    deps = "";
                }
                callback._name = "@"+name; //模块名
                this.require(deps,callback);
            },
            require:function(deps,callback,errback){//依赖列表,正向回调,负向回调
                var _deps = {}, args = [], dn = 0, cn = 0;
                (deps +"").replace(mass.rword,function(url,name,match){
                    dn++;
                    match = url.match(rmodule);
                    name = "@"+ match[1];//取得模块名
                    if(!map[name]){ //防止重复生成节点与请求
                        map[name] = { };//state: undefined, 未加载; 1 已加载; 2 : 已执行
                        useNativeRequire(name,match[2]);//加载模块
                    }else if(map[name].state === 2){
                        cn++;
                    }
                    if(!_deps[name] ){
                        args.push(name);
                        _deps[name] = "司徒正美";//去重
                    }
                });
                var cbname = callback._name;
                if(dn === cn ){//在依赖都已执行过或没有依赖的情况下
                    if(cbname && !(cbname in rets)){
                        map[cbname].state = 2 //如果是使用合并方式,模块会跑进此分支(只会执行一次)
                        return rets[cbname] =  callback.apply(null,incarnate(args));   
                    }else if(!cbname){//普通的回调可执行无数次
                        return callback.apply(null,incarnate(args))
                    }
                }
                cbname = cbname || "@cb"+ (cbi++).toString(32);
    
                if(errback){
                    mass.stack(errback);//压入错误堆栈
                }
                map[cbname] = {//创建或更新模块的状态
                    callback:callback,
                    deps:_deps,
                    args: args,
                    state: 1
                };//在正常情况下模块只能通过resolveCallbacks执行
                names.unshift(cbname);
                resolveCallbacks();
            }
            
        });
    
    
        exports.mass = global.mass = mass;
    })();
    
  • 相关阅读:
    Go基础数据类型
    在foreach中使用distinct查找不重复记录
    DataTable,List去重复记录的方法(转载)
    ArcEngine的IMap接口(转载)
    根据Excel表格建立Shp文件(开发详解及源代码)(转载)
    axmapcontrol和mapcontrol有什么区别呢(转发)
    DataSet多表查询操作(转载)
    c#调用DLL(转载)
    wall 系列技术贴
    ArcEngine的IFeaturLayer接口(转载)
  • 原文地址:https://www.cnblogs.com/rubylouvre/p/2276390.html
Copyright © 2011-2022 走看看