UNPKG

atm-command-generate

Version:
315 lines (292 loc) 9.71 kB
var define = null; var atmjs = {}; (function (win) { var loaderNode = document.getElementById('atmjsnode'), // atmjs加载器的script节点 baseUrl = loaderNode.getAttribute('data-base'), // 静态资源路径前缀 config = loaderNode.getAttribute('data-config'), // 异步数据配置 uriList = {}, // 文件id对应的文件全路径 list = {}, needs = {}, // require.use || require.async 加载的id数组 modules = {}, // 存放执行过后的模块接口数据 cssExists = {},// {cssFileId1: 1, cssFileId2: 1}, asyncQueues = [], atmLoader = atmjs.loader = { baseUrl: baseUrl, uriList: uriList, // undefined 尚未加载 // 10 加载中 // 20 加载成功且依赖正在加载中 // 30 加载成功且依赖已全部执行成功 // 40 自身执行完成 // 50 加载失败 modules: modules, needs: needs, list: list, asyncQueues: asyncQueues, asyncDeps: {}, cssExists: cssExists }; function useOrAsync(timeout) { function cb(ids, factory) { ids = getIds(ids); var deps = arrToObj(ids); addNeeds(ids); asyncQueues.push({ deps: deps, factory: factory }); // 如果所依赖的模块还有未执行的 if (!getStatus(deps)) { for (var id in deps) { //尝试执行所依赖的模块 tryExecModule(id); } } else { // 执行异步队列 execAsync(); } } return function (ids, factory) { if (timeout) { setTimeout(function () { cb(ids, factory); }, 0); } else { cb(ids, factory); } }; } atmjs.use = useOrAsync(false); require.async = useOrAsync(true); // define(id, dependencies?, factory) define = function (id, depsArr, factory) { if (typeof depsArr === 'function') { factory = depsArr; depsArr = []; } var deps = arrToObj(depsArr); // 如果该文件之前的状态为 未加载或正在加载中 ,则改变status为20,说明该文件已经加载成功 if (!list[id] || list[id].status === 10) { list[id] = { id: id, status: 20, factory: factory, deps: deps }; // 如果该文件在needs列表里面,则尝试执行该文件 if (needs[id]) { tryExecModule(id); } } }; function execModule(id) { if (!needs[id]) { return; } //执行factory var factory = list[id].factory; var module = modules[id] = { exports: {} }; var ret = typeof factory === 'function' ? factory.apply(win, [require, module.exports, module]) : factory; if (typeof ret !== 'undefined'){ module.exports = ret; } list[id].status = 40; execAsync(); for (var i in list){ if (list[i].deps[id] && list[i].status === 20){ var deps = list[i].deps; if (getStatus(deps)){ execModule(i); } } } } function tryExecModule(id) { // 如果还没有该id对应的信息,则找到该id对应的url去加载,同时在list中设置该id的status为10,说明该id已开始加载 if (!list[id]){ // needs[id] = 1; // 如果该id文件依赖css,则首先去加载所依赖的css文件 if (atmLoader.asyncDeps[id]) { var arr = atmLoader.asyncDeps[id]; addCss(arr); } var uri = getUri(id); if(!uri){ throw new Error('无法找到['+id+']对应的路径'); } createScript(uri); list[id] = { status: 10, deps: {} }; } else if (list[id].status === 20) { // 如果该id文件已加载成功 var deps = list[id].deps; // 判断依赖是否全部执行完成,如果依赖全部执行完成,则改变id在list中的status值为30 if (getStatus(deps)) { execModule(id); } else { // 如果有依赖没有执行,则执行依赖 for (var i in deps) { needs[i] = 1; tryExecModule(i); } } } } //atmjs.use&require.async内部调用的函数 function execAsync() { // 如果异步队列为空,则跳出 if (!asyncQueues.length) { return; } // 找出依赖都执行完毕的项 var arr = []; for (var i in asyncQueues) { if (getStatus(asyncQueues[i].deps)) { arr.push(asyncQueues.splice(i, 1)[0]); } } if (!arr.length) { return; } for (var i in arr) { var obj = arr[i], factory = obj.factory; if (typeof factory === 'function') { var deps = getIds(obj.deps), mods = []; for (var id in deps) { mods.push(modules[id].exports); } factory.apply(win, mods); } } execAsync(); } function setConfig(cfg) { //var cfg = { // 加载&解析器用到的配置数据 // async: { // async数据 // alias: { // id与uri的对应关系 // id1: 'uri1', // id2: 'uri2' // }, // deps: { // js文件id依赖的cssid数组 // jsid1: ['depend css id1', 'depend css id2', 'depend css idN'], // jsid2: ['depend css id1', 'depend css id2', 'depend css idN'] // }, // exists: { // 页面中已经存在的css文件的id,用于ajax创建css标签时的判断 // cssid1: 1, // cssid2: 1 // } // } // // other to be set by user //}; cfg = cfg || {}; var asyncConfig = cfg.async || {}; var alias = asyncConfig.alias || {}; var asyncDeps = asyncConfig.deps || {}; var cssExists = asyncConfig.exists || {}; for (var id in alias) { uriList[id] = baseUrl + alias[id]; } for (var id in asyncDeps) { var depsArr = [], data = asyncDeps[id]; for (var i in data) { if (!cssExists[data[i]]) { depsArr.push(uriList[data[i]]); } } asyncDeps[id] = depsArr; } atmLoader.asyncDeps = asyncDeps; atmLoader.cssExists = cssExists; }; function addCss(uriArr) { for (var i in uriArr) { var uri = uriArr[i]; if(uri.indexOf(baseUrl) === -1){ uri = baseUrl + uri; } if(!atmLoader.cssExists[uri] && uri){ createStylesheet(uri); } } } if (config) { config = (new Function('return ' + config))(); setConfig(config); } function addNeeds(ids) { var id; for (var i in ids) { id = ids[i]; needs[id] = 1; } } // 所依赖的js的加载状态 function getStatus(deps) { var status = true; for (var id in deps){ if (!list[id] || list[id].status < 40){ return false; } } return status; } // 定义require function require(id) { return modules[id].exports; } // 如果ids是字符串,则转换为数组返回 function getIds(ids) { return typeof ids==='string'? [ids]: ids; } // 获取id对应的url路径 function getUri(id) { return uriList[id]; } // 创建js节点 var createdJs = {}; function createScript(url) { if (createdJs[url]) { return; } createdJs[url] = true; var script = document.createElement('script'); script.type = 'text/javascript'; script.src = url; var firstScript = document.getElementsByTagName('script')[0]; firstScript.parentNode.insertBefore(script, firstScript); return script; } // 创建css节点 var createdCss = {} function createStylesheet(href) { if (createdCss[href]) { return; } createdCss[href] = true; var head = document.getElementsByTagName('head')[0]; var link = document.createElement('link'); link.href = href; link.rel = 'stylesheet'; link.type = 'text/css'; head.appendChild(link); } // 把 数组转换为对象 // eg: ['a','b'] To {a: 1, b: 1} function arrToObj(arr) { var obj = {}; for (var i in arr) { var id = arr[i]; obj[id] = 1; } return obj; } })(window);