amis/examples/mod.js

308 lines
6.5 KiB
JavaScript
Raw Permalink Normal View History

2019-04-30 11:11:25 +08:00
/**
* @file 模块加载器改成私有化的了慎用
2019-04-30 11:11:25 +08:00
*/
/* eslint-disable */
2019-04-30 11:11:25 +08:00
(function (global) {
var require, define;
var amis = window.amis || {};
// 避免重复加载而导致已定义模块丢失
if (amis.require) {
return;
}
var head = document.getElementsByTagName('head')[0];
var loadingMap = {};
var factoryMap = {};
var modulesMap = {};
var scriptsMap = {};
var resMap = {};
var pkgMap = {};
var createScripts = function (queues, onerror) {
var docFrag = document.createDocumentFragment();
for (var i = 0, len = queues.length; i < len; i++) {
var id = queues[i].id;
var url = queues[i].url;
if (url in scriptsMap) {
continue;
}
scriptsMap[url] = true;
var script = document.createElement('script');
if (onerror) {
(function (script, id) {
var tid = setTimeout(function () {
onerror(id);
}, require.timeout);
script.onerror = function () {
clearTimeout(tid);
onerror(id);
};
var onload = function () {
clearTimeout(tid);
};
if ('onload' in script) {
script.onload = onload;
} else {
script.onreadystatechange = function () {
if (
this.readyState === 'loaded' ||
this.readyState === 'complete'
) {
onload();
}
};
}
})(script, id);
}
script.type = 'text/javascript';
script.src = url;
docFrag.appendChild(script);
}
2019-04-30 11:11:25 +08:00
head.appendChild(docFrag);
};
var loadScripts = function (ids, callback, onerror) {
var queues = [];
for (var i = 0, len = ids.length; i < len; i++) {
var id = ids[i];
var queue = loadingMap[id] || (loadingMap[id] = []);
queue.push(callback);
//
// resource map query
//
var res = resMap[id] || resMap[id + '.js'] || {};
var pkg = res.pkg;
var url;
if (pkg) {
url = pkgMap[pkg].url || pkgMap[pkg].uri;
} else {
url = res.url || res.uri || id;
}
queues.push({
id: id,
url: url
});
2019-04-30 11:11:25 +08:00
}
createScripts(queues, onerror);
};
var runQueue = function (id) {
var queue = loadingMap[id];
if (queue) {
for (var i = 0, n = queue.length; i < n; i++) {
queue[i]();
}
delete loadingMap[id];
}
};
define = function (id, factory) {
id = id.replace(/\.js$/i, '');
factoryMap[id] = factory;
if (~factory.toString().indexOf('__mod__async__load')) {
var mod = {exports: {}};
factoryMap[id] = {
deffer: true,
callbacks: [],
loaded: false,
load: function () {}
};
factory.apply(mod, [require, mod.exports, mod]);
var load = mod.exports.__mod__async__load;
factoryMap[id].load = function () {
if (this.loaded) {
return;
2019-04-30 11:11:25 +08:00
}
this.loaded = true;
load(function (ret) {
var callbacks = factoryMap[id].callbacks;
factoryMap[id] = function () {
return ret;
};
callbacks.forEach(function (fn) {
fn();
});
runQueue(id);
});
};
if (loadingMap[id] && loadingMap[id].length) {
factoryMap[id].load();
}
} else {
runQueue(id);
}
};
2019-04-30 11:11:25 +08:00
require = function (id) {
// compatible with require([dep, dep2...]) syntax.
if (id && id.splice) {
return require.async.apply(this, arguments);
}
2019-04-30 11:11:25 +08:00
id = require.alias(id);
2019-04-30 11:11:25 +08:00
var mod = modulesMap[id];
if (mod) {
return mod.exports;
}
2019-04-30 11:11:25 +08:00
//
// init module
//
var factory = factoryMap[id];
if (!factory) {
throw '[ModJS] Cannot find module `' + id + '`';
}
2019-04-30 11:11:25 +08:00
mod = modulesMap[id] = {
exports: {}
2019-04-30 11:11:25 +08:00
};
//
// factory: function OR value
//
var ret =
typeof factory === 'function'
? factory.apply(mod, [require, mod.exports, mod])
: factory;
2019-04-30 11:11:25 +08:00
if (ret) {
mod.exports = ret;
}
2019-04-30 11:11:25 +08:00
return mod.exports;
};
2019-04-30 11:11:25 +08:00
require.async = function (names, onload, onerror) {
if (typeof names === 'string') {
names = [names];
}
2019-04-30 11:11:25 +08:00
var needMap = {};
var needNum = 0;
var needLoad = [];
2019-04-30 11:11:25 +08:00
function findNeed(depArr) {
var child;
2019-04-30 11:11:25 +08:00
for (var i = 0, n = depArr.length; i < n; i++) {
2019-04-30 11:11:25 +08:00
//
// skip loading or loaded
2019-04-30 11:11:25 +08:00
//
var dep = require.alias(depArr[i]);
2019-04-30 11:11:25 +08:00
if (dep in needMap) {
continue;
2019-04-30 11:11:25 +08:00
}
needMap[dep] = true;
if (dep in factoryMap) {
if (factoryMap[dep] && factoryMap[dep].deffer) {
needNum++;
factoryMap[dep].callbacks.push(updateNeed);
factoryMap[dep].load();
}
// check whether loaded resource's deps is loaded or not
child = resMap[dep] || resMap[dep + '.js'];
if (child && 'deps' in child) {
findNeed(child.deps);
}
continue;
2019-04-30 11:11:25 +08:00
}
needLoad.push(dep);
needNum++;
2019-04-30 11:11:25 +08:00
child = resMap[dep] || resMap[dep + '.js'];
if (child && 'deps' in child) {
findNeed(child.deps);
2019-04-30 11:11:25 +08:00
}
}
}
2019-04-30 11:11:25 +08:00
function updateNeed() {
if (0 === needNum--) {
var args = [];
for (var i = 0, n = names.length; i < n; i++) {
args[i] = require(names[i]);
2019-04-30 11:11:25 +08:00
}
onload && onload.apply(global, args);
}
}
2019-04-30 11:11:25 +08:00
findNeed(names);
loadScripts(needLoad, updateNeed, onerror);
updateNeed();
};
require.ensure = function (names, callback) {
require.async(names, function () {
callback && callback.call(this, require);
});
};
require.resourceMap = function (obj) {
var k;
var col;
// merge `res` & `pkg` fields
col = obj.res;
for (k in col) {
if (col.hasOwnProperty(k)) {
resMap[k] = col[k];
}
}
2019-04-30 11:11:25 +08:00
col = obj.pkg;
for (k in col) {
if (col.hasOwnProperty(k)) {
pkgMap[k] = col[k];
}
}
};
2019-04-30 11:11:25 +08:00
require.loadJs = function (url) {
if (url in scriptsMap) {
return;
}
2019-04-30 11:11:25 +08:00
scriptsMap[url] = true;
2019-04-30 11:11:25 +08:00
var script = document.createElement('script');
script.type = 'text/javascript';
script.src = url;
head.appendChild(script);
return script;
};
2019-04-30 11:11:25 +08:00
require.alias = function (id) {
return id.replace(/\.js$/i, '');
};
2019-04-30 11:11:25 +08:00
require.timeout = 5000;
2019-04-30 11:11:25 +08:00
amis.require = require;
amis.define = define;
window.amis = amis;
// window.require = window.require || require;
2019-04-30 11:11:25 +08:00
})(this);