不要温柔地走入AMD

1.无依赖情况

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>一步步走入AMD</title>
    <script>

    var req = {};
    /*无依赖*/
    req.config = {
        "a":{
            deps:[],
            fn:function(){
                console.log("a");
            }
        },
        "b":{
            deps:[],
            fn:function(){
                console.log("b");
            }
        },
        "c":{
            deps:[],
            fn:function(){
                console.log("c");
            }
        },
    }
    var require = function(deps,fn){
        var config = req.config,
        deps_arr = [];

        // 1.找依赖,生成依赖数组
        for(var i=0,l = deps.length; i<l; i++){
            var deps_item = deps[i];
            deps_arr.push(config[deps_item].fn);
        }

        // 2.依赖数组,是入口函数的参数
        fn.apply(window,deps_arr);
    };

    require(["a","b"],function(a,b){
        a();
        b();
    });
    </script>
</head>
<body>

</body>
</html>

2.有依赖

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>不要温柔地走入AMD</title>
    <script>
    var req = {};
    /*有依赖*/
    req.config = {
        "a":{
            deps:["b"],
            fn:function(b){
                return function(){
                    console.log("a");
                    b();
                }

            }
        },
        "b":{
            deps:["c"],
            fn:function(c){
                return function(){
                    console.log("b");
                    c();
                }

            }
        },
        "c":{
            deps:[],
            fn:function(){
                var private_c = "cc"
                return function(){
                    console.log("c");
                    console.log(private_c);
                }

            }
        }
    }
    var require = function(deps,fn){
        var config = req.config,
        deps_arr = [];

        var excute_obj = {},
        deps_chain = [];

        for(var i in config){
            deps_chain.push(i);
        }

        // 包装各个依赖函数
        deps_chain.forEach(function(configName){
            var item = config[configName],
            item_deps = item["deps"],
            item_fn = function(){
                return item["fn"].apply(window,excute_obj[configName]["deps"])();
            };
            excute_obj[configName] = {};
            excute_obj[configName]["fn"] = item_fn;

        });

        // 依赖函数的执行参数生成
        deps_chain.forEach(function(configName){
            var item = config[configName],
            item_deps = item["deps"],
            param_arr = [];

            item_deps.forEach(function(i){
                param_arr.push(excute_obj[i]["fn"]);
            });

            excute_obj[configName]["deps"] = param_arr;

        });

        console.log(excute_obj);

        deps.forEach(function(configName){
            deps_arr.push(excute_obj[configName]["fn"]);
        });

        fn.apply(window,deps_arr);
    };

    // bug:依赖设置错误
    require(["a"],function(a){
        a();

    });
    </script>
</head>
<body>

</body>
</html>

3.循环依赖判断

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>不要温柔地走入AMD</title>
    <script>
    var req = {};
    /*有循环依赖*/
    req.config = {
        "a":{
            deps:["b","c"],
            fn:function(b,c){
                return function(){
                    console.log("a");
                    b();
                    c();
                }

            }
        },
        "b":{
            deps:["c"],
            fn:function(c){
                return function(){
                    console.log("b");
                    c();
                }

            }
        },
        "c":{
            deps:["a"],
            fn:function(){
                return function(){
                    console.log("c");
                }

            }
        }
    }
    var require = function(deps,fn){
        var config = req.config,
        deps_arr = [];

        var excute_obj = {},
        deps_chain = [];

        for(var i in config){
            deps_chain.push(i);
        }
        console.log(deps_chain);

        function arrayClone(arr){
            var _array = [];
            for(var i=0,l=arr.length; i<l; i++){
                _array.push(arr[i]);
            }

            return _array;
        }
        function loopDepJudge(currentKey,currentDeps, circleArr){
            var check_arr = [];
            check_arr.unshift(arrayClone(currentDeps) );

            var keyChain = [currentKey];
            // 开始循环
            (function(){
                var currentDeps = check_arr[0];
                // console.log(currentDeps);
                if(currentDeps.length > 0){
                    var nextKey = currentDeps.shift(),
                    nextDeps = circleArr[nextKey];
                    if(keyChain.indexOf(nextKey) > -1){
                        keyChain = [false,nextKey,keyChain.pop()];
                        return;
                    }
                    else{
                        keyChain.push(nextKey);
                    }

                    if(nextDeps.length > 0){
                        check_arr.unshift(arrayClone(nextDeps));
                    }
                    else{
                        check_arr.shift();
                        keyChain = [currentKey];
                        if(check_arr.length == 0){
                            return;
                        }
                    }
                }
                else{
                    return;
                }
                arguments.callee();
            })();
            return keyChain;
        }

        (function(){
            // 循环依赖检测
            var circle_deps = {};
            deps_chain.forEach(function(configName){
                circle_deps[configName] = config[configName]["deps"];
            });

            deps_chain.forEach(function(configName){
                var key = configName,
                deps = arrayClone(circle_deps[key]);

                var keyChain = loopDepJudge(key,deps,circle_deps);
                if(keyChain[0] == false){
                    throw new Error("有循环依赖。他们是"+keyChain[1]+"和" +keyChain[2]);
                }
                else{
                    console.log(keyChain)
                }
            });
            // var keyChain = loopDepJudge()

            // 包装各个依赖函数
            deps_chain.forEach(function(configName){
                var item = config[configName],
                item_deps = item["deps"],
                item_fn = function(){
                    return item["fn"].apply(window,excute_obj[configName]["deps"])();
                };

                excute_obj[configName] = {};
                excute_obj[configName]["fn"] = item_fn;

            });

            // 依赖函数的执行参数生成
            deps_chain.forEach(function(configName){
                var item = config[configName],
                item_deps = item["deps"],
                param_arr = [];

                item_deps.forEach(function(i){
                    param_arr.push(excute_obj[i]["fn"]);
                });

                excute_obj[configName]["deps"] = param_arr;

            });

            console.log(excute_obj);

        })();

        deps.forEach(function(configName){
            deps_arr.push(excute_obj[configName]["fn"]);
        });

        fn.apply(window,deps_arr);
    };

    require(["a"],function(a){
        a();

    });
    </script>
</head>
<body>

</body>
</html>

4.define函数定义

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>不要温柔地走入AMD</title>
    <script>
    var req = {};
    /*define函数定义*/
    req.requireConfig = {};

    var define = function(deps,fn){
        var protocal = location.protocal,
        host = location.host,
        port = location.port,
        pathName = location.pathname,
        href = location.href,

        paths = req.userConfig.paths,
        baseUrl = req.userConfig.baseUrl || "";

        function baseUrlParse(baseUrl){
            var str_length = baseUrl.length,
            newBaseUrl = "";
            if(baseUrl.lastIndexOf("/") == str_length -1){

            }
            else{
                newBaseUrl = baseUrl + "/";
            }
            return newBaseUrl;
        }

        // 不支持IE
        // 1.获取当前js文件地址
        var scriptSrc = document.currentScript.src;

        for (var i in paths) {
            var path = paths[i],
            complete_path = "";

            // 2. 生成complete_path

            var backslash_pos = href.lastIndexOf("/"),
            slash_href = href.substring(0,backslash_pos+1),
            complete_path = slash_href + baseUrlParse(baseUrl) + path;

            // 3. 根据文件地址进行匹配,从而生成req.requireConfig
            if(scriptSrc == complete_path){
                req.requireConfig[i] = {
                    "deps":deps,
                    "fn":fn
                };
            }
        };
    };
    var require = function(deps,fn){
        function arrayClone(arr){
            var _array = [];
            for(var i=0,l=arr.length; i<l; i++){
                _array.push(arr[i]);
            }

            return _array;
        }
        function loopDepJudge(currentKey,currentDeps, circleArr){
            var check_arr = [];
            check_arr.unshift(arrayClone(currentDeps) );

            var keyChain = [currentKey];
            // 开始循环
            (function(){
                var currentDeps = check_arr[0];
                // console.log(currentDeps);
                if(currentDeps.length > 0){
                    var nextKey = currentDeps.shift(),
                    nextDeps = circleArr[nextKey];
                    if(keyChain.indexOf(nextKey) > -1){
                        keyChain = [false,nextKey,keyChain.pop()];
                        return;
                    }
                    else{
                        keyChain.push(nextKey);
                    }

                    if(nextDeps.length > 0){
                        check_arr.unshift(arrayClone(nextDeps));
                    }
                    else{
                        check_arr.shift();
                        keyChain = [currentKey];
                        if(check_arr.length == 0){
                            return;
                        }
                    }
                }
                else{
                    return;
                }
                arguments.callee();
            })();
            return keyChain;
        }

        var config = req.requireConfig,
        deps_arr = [],
        excute_obj = {},
        deps_chain = [];

        for(var i in config){
            deps_chain.push(i);
        }

        // 循环依赖检测
        (function(){
            var circle_deps = {};
            deps_chain.forEach(function(configName){
                circle_deps[configName] = config[configName]["deps"];
            });

            deps_chain.forEach(function(configName){
                var key = configName,
                deps = arrayClone(circle_deps[key]);

                var keyChain = loopDepJudge(key,deps,circle_deps);
                if(keyChain[0] == false){
                    throw new Error("有循环依赖。他们是"+keyChain[1]+"和" +keyChain[2]);
                }
                else{
                    console.log(keyChain)
                }
            });
        })();

        deps_chain.forEach(function(depsItem){
            var configItem_deps = config[depsItem]["deps"];
            configItem_deps.forEach(function(loopItem){
                if(config[loopItem]["deps"].indexOf(depsItem) > -1){
                    throw new Error("前方高能预警,有循环依赖。它们是" + depsItem+"和"+loopItem);
                    return;
                }
            });

        });

        // 包装各个依赖函数
        deps_chain.forEach(function(configName){
            var item = config[configName],
            item_deps = item["deps"],
            item_fn = function(){
                return item["fn"].apply(window,excute_obj[configName]["deps"])();
            };
            excute_obj[configName] = {};
            excute_obj[configName]["fn"] = item_fn;

        });

        // 依赖函数的参数数组生成
        deps_chain.forEach(function(configName){
            var item = config[configName],
            item_deps = item["deps"],
            param_arr = [];

            item_deps.forEach(function(i){
                param_arr.push(excute_obj[i]["fn"]);
            });

            excute_obj[configName]["deps"] = param_arr;

        });

        // 主函数的参数数组生成
        deps.forEach(function(configName){
            deps_arr.push(excute_obj[configName]["fn"]);
        });

        fn.apply(window,deps_arr);
    };

    req.userConfig = {
        "baseUrl":"",
        "paths":{
            "a":"a.js",
            "b":"b.js",
            "c":"c.js"
        }
    };
    </script>
    <script type="text/javascript" src="b.js"></script>
    <script type="text/javascript" src="a.js"></script>
    <script type="text/javascript" src="c.js"></script>
    <script>
    require(["a"],function(a){
        a();
    });
    </script>
</head>
<body>

</body>
</html>

5.js加载器生成

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>不要温柔地走入AMD</title>
    <script>
    /*
    1.不支持延迟加载js
    2.当前循环依赖检测尚有bug
    3.不支持shim
    */
    var req = {};

    req.requireConfig = {};
    req.userConfig= {};
    // 用来记录js加载的数目
    req.jsLoadCount = 0;

    function baseUrlParse(baseUrl){
        var str_length = baseUrl.length,
        newBaseUrl = "";
        if(baseUrl.lastIndexOf("/") == str_length -1){

        }
        else{
            newBaseUrl = baseUrl + "/";
        }
        return newBaseUrl;
    }

    function getObjSize(obj){
        var size = 0;
        for(var i in obj){
            var item = obj[i];
            if(item !== null && typeof(item) !== "undefined"){
                size++;
            }
        }

        return size;
    }

    var define = function(deps,fn){
        var protocal = location.protocal,
        host = location.host,
        port = location.port,
        pathName = location.pathname,
        href = location.href,

        paths = req.userConfig.paths,
        baseUrl = req.userConfig.baseUrl || "";

        // 不支持IE
        // 1.获取当前js文件地址
        var scriptSrc = document.currentScript.src;

        for (var i in paths) {
            var path = paths[i],
            complete_path = "";

            // 2. 生成complete_path
            var backslash_pos = href.lastIndexOf("/"),
            slash_href = href.substring(0,backslash_pos+1),
            complete_path = slash_href + baseUrlParse(baseUrl) + path;

            // 3. 根据文件地址进行匹配,从而生成req.requireConfig
            if(scriptSrc == complete_path){
                req.requireConfig[i] = {
                    "deps":deps,
                    "fn":fn
                };
            }
        };
    };
    var require = function(deps,fn){
        // 检测js加载完毕与否
        var timer_loader = setTimeout(function(){
            if(req.jsLoadCount == 0){
                clearTimeout(timer_loader);
                mainRequire();
            }
            else{
                timer_loader();
            }
        },200);

function mainRequire(){
        function arrayClone(arr){
            var _array = [];
            for(var i=0,l=arr.length; i<l; i++){
                _array.push(arr[i]);
            }

            return _array;
        }
        function loopDepJudge(currentKey,currentDeps, circleArr){
            var check_arr = [];
            check_arr.unshift(arrayClone(currentDeps) );

            var keyChain = [currentKey];
            // 开始循环
            (function(){
                var currentDeps = check_arr[0];
                // console.log(currentDeps);
                if(currentDeps.length > 0){
                    var nextKey = currentDeps.shift(),
                    nextDeps = circleArr[nextKey];
                    if(keyChain.indexOf(nextKey) > -1){
                        keyChain = [false,nextKey,keyChain];
                        return;
                    }
                    else{
                        keyChain.push(nextKey);
                    }

                    if(nextDeps.length > 0){
                        check_arr.unshift(arrayClone(nextDeps));
                    }
                    else{
                        check_arr.shift();
                        keyChain = [currentKey];
                        if(check_arr.length == 0){
                            return;
                        }
                    }
                }
                else{
                    return;
                }
                arguments.callee();
            })();
            return keyChain;
        }
        var config = req.requireConfig,
        deps_arr = [],
        excute_obj = {},
        deps_chain = [];

        for(var i in config){
            deps_chain.push(i);
        }
        console.log(config);

        // 循环依赖检测
        (function(){
            var circle_deps = {};
            deps_chain.forEach(function(configName){
                circle_deps[configName] = config[configName]["deps"];
            });
            console.log(circle_deps);

            deps_chain.forEach(function(configName){
                var key = configName,
                deps = arrayClone(circle_deps[key]);

                var keyChain = loopDepJudge(key,deps,circle_deps);
                if(keyChain[0] == false){
                    throw new Error("前方高能,有循环依赖。他们是"+keyChain[1]+"和" +keyChain[2]);
                }
                else{
                    console.log(keyChain)
                }
            });
        })();

        // 包装各个依赖函数
        deps_chain.forEach(function(configName){
            var item = config[configName],
            item_deps = item["deps"],
            item_fn = function(){
                return item["fn"].apply(window,excute_obj[configName]["deps"])();
            };
            excute_obj[configName] = {};
            excute_obj[configName]["fn"] = item_fn;

        });

        // 依赖函数的参数数组生成
        deps_chain.forEach(function(configName){
            var item = config[configName],
            item_deps = item["deps"],
            param_arr = [];

            item_deps.forEach(function(i){
                param_arr.push(excute_obj[i]["fn"]);
            });

            excute_obj[configName]["deps"] = param_arr;

        });

        // 主函数的参数数组生成
        deps.forEach(function(configName){
            deps_arr.push(excute_obj[configName]["fn"]);
        });

        fn.apply(window,deps_arr);
}
    };
    require.config = function(config_obj){
        req.userConfig = config_obj;
        req.jsLoadCount = getObjSize(config_obj.paths);

        function generateScript(url,loadCount){
            var _script = document.createElement(‘script‘);
            _script.type = ‘text/javascript‘;
            _script.charset = ‘utf-8‘;
            _script.async = true;
            _script.src = url;
            _script.onload = function(){
                req.jsLoadCount--;
            };
            _script.onerror = function(e){
                throw new Error(e);
            };

            var fs = document.getElementsByTagName(‘script‘)[0];
              fs.parentNode.insertBefore(_script, fs);
        }
        var href = location.href,
        baseUrl = req.userConfig.baseUrl || "";
        paths =  req.userConfig.paths;
        for(var i in paths){
            var path = paths[i],
            backslash_pos = href.lastIndexOf("/"),
            slash_href = href.substring(0,backslash_pos+1),
            complete_path = slash_href + baseUrlParse(baseUrl) + path;
            generateScript(complete_path);
        }

    }

    require.config({
        "baseUrl":"",
        "paths":{
            "c":"c.js?v=3",
            "a":"a.js",
            "b":"b.js"
        }
    });

    require(["a","b"],function(a,b){
        a();
        b();
    });

    </script>

</head>
<body>

</body>
</html>
时间: 2024-12-03 10:43:24

不要温柔地走入AMD的相关文章

不要温柔地走入promise

第零步 <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>链式化</title> <script type="text/javascript"> (function(){ function Promise(fn){ var instance = this; instance["_value"]

浅析JS模块规范:AMD,CMD,CommonJS

随着JS模块化编程的发展,处理模块之间的依赖关系成为了维护的关键. 模块化 AMD,CMD,CommonJS是目前最常用的三种模块化书写规范. CommonJS CommonJS规范是诞生比较早的.NodeJS就采用了CommonJS.是这样加载模块: var clock = require('clock'); clock.start(); 这种写法适合服务端,因为在服务器读取模块都是在本地磁盘,加载速度很快.但是如果在客户端,加载模块的时候有可能出现"假死"状况.比如上面的例子中cl

AMD 的 CommonJS wrapping

其实本文的标题应该是「为什么我不推荐使用 AMD 的 Simplified CommonJS wrapping」,但太长了不好看,为了美观我只能砍掉一截. 它是什么? 为了复用已有的 CommonJS 模块,AMD 规定了 Simplified CommonJS wrapping,然后 RequireJS 实现了它(先后顺序不一定对).它提供了类似于 CommonJS 的模块定义方式,如下: JSdefine(function(require, exports, module) { var A

avalon学习笔记ui篇-如何将avalon默认的amd模型禁止,以及用require重写。

一.如何禁止avalon自带的amd模型 1.采用avalon.shim.js这个文件,这个文件删除了原本自带的amd模型,不需要手动删除,修改. 2.打开avalon.js这个文件,搜索avalon.config,将true改为false. 二,下载text.js和css.js 1.因为avalonUI依赖了html文件和css文件. 2.并且将text.js和css.js,在配置中预加载 priority:['text','css'] 三.完整配置项 require.config({ //b

java.lang.UnsatisfiedLinkError: D:\apache-tomcat-7.0.57\bin\tcnative-1.dll: Can&#39;t load IA 32-bit .dll on a AMD 64-bit platform 错误

为了开发JavaWEB,安装了MyEclipse,在运行tomcat的时候发现报错:java.lang.UnsatisfiedLinkError: D:\apache-tomcat-7.0.57\bin\tcnative-1.dll: Can't load IA 32-bit .dll on a AMD 64-bit platform.自己上网查了下,发现这个错误对于项目的运行时没有什么大碍的,可能自己有强迫症,总是想没错,就上网找了解决方法.我先麻烦,就选择了最简单的方法,去tomcat目录下

关于commonjs,AMD,CMD之间的异同

1.简介 随着前端业务复杂度的增加,模块化成为一个大的趋势.而在ES6还未被浏览器所支持的情况下,commonjs作为ES6中标准模块加载方案,在客服端中的支持情况并不好,现在在客服端中有2中模块化的解决方案,CMD和AMD,他们的代表分别为seajs和requirejs.这篇文章主要介绍我对commonjs.AMD以及CMD的理解. 2.commonJS commonjs的目标是制定一个js模块化的标准,它的目标制定一个可以同时在客服端和服务端运行的模块.这些模块拥有自己独立的作用域,也可以向

Javascript模块化编程(二):AMD规范

作者: 阮一峰 日期: 2012年10月30日 这个系列的第一部分介绍了Javascript模块的基本写法,今天介绍如何规范地使用模块. (接上文) 七.模块的规范 先想一想,为什么模块很重要? 因为有了模块,我们就可以更方便地使用别人的代码,想要什么功能,就加载什么模块. 但是,这样做有一个前提,那就是大家必须以同样的方式编写模块,否则你有你的写法,我有我的写法,岂不是乱了套!考虑到Javascript模块现在还没有官方规范,这一点就更重要了. 目前,通行的Javascript模块规范共有两种

AMD CMD 和 CommonJS

JS中的模块规范(CommonJS,AMD,CMD),如果你听过js模块化这个东西,那么你就应该听过或CommonJS或AMD甚至是CMD这些规范咯,我也听过,但之前也真的是听听而已. 现在就看看吧,这些规范到底是啥东西,干嘛的.本文包括这三个规范的来源及对应的产物的原理. 一.CommonJS 1.一开始大家都认为JS是辣鸡,没什么用,官方定义的API只能构建基于浏览器的应用程序,逗我呢,这太狭隘了吧(用了个高端词,嘎嘎),CommonJS就按耐不住了,CommonJS API定义很多普通应用

AMD:RX 480双卡就这样灭GTX 1080!

日前宣布新卡Radeon RX 480的时候,AMD做了一番性能演示,同时使用RX 480双卡.GTX 1080单卡跑DX12游戏<奇点灰烬>的基准测试,结果前者完胜. 要知道,GTX 1080只要199美元,两块加起来也不到400美元,GTX 1080的两个版本则是599/699美元. 那么,AMD是怎么做到的呢? AMD全球技术营销总监Robert Hallock特意对此做了详细解释,尤其是给出了测试平台配置: Core i7-5930K处理器.华擎X99M Killer主板.32GB D