var doc = document; var head = doc.head || doc.getElementsByTagName("head")[0] || doc.documentElement; var baseElement = head.getElementsByTagName("base")[0];
functionrequest(url, callback, charset, crossorigin) { var node = doc.createElement("script");
if (charset) { node.charset = charset; }
if (!isUndefined(crossorigin)) { node.setAttribute("crossorigin", crossorigin); }
addOnload(node, callback, url);
node.async = true; node.src = url;
// For some cache cases in IE 6-8, the script executes IMMEDIATELY after // the end of the insert execution, so use `currentlyAddingScript` to // hold current node, for deriving url in `define` call currentlyAddingScript = node;
crossorigin: The CORS options, Don’t set CORS on default.
alias: An object containing shorthands of module id
paths: An object containing path shorthands in module id
vars: The {xxx} variables in module id
map: An array containing rules to map module uri
debug: Debug mode. The default value is false
seajs.resolve
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
functionid2Uri(id, refUri) { if (!id) return"";
id = parseAlias(id); // 如果有 Alias, 就使用 alias 中的路径 id = parsePaths(id); // 如果 data.paths 中有,则使用 paths 中的路径 id = parseAlias(id); id = parseVars(id); id = parseAlias(id); id = normalize(id); id = parseAlias(id);
var uri = addBase(id, refUri); uri = parseAlias(uri); uri = parseMap(uri);
// Parse dependencies according to the module factory code if (!isArray(deps) && isFunction(factory)) { deps = typeof parseDependencies === "undefined" ? [] : parseDependencies(factory.toString()); }
var meta = { id: id, uri: Module.resolve(id), deps: deps, factory: factory, };
// Try to derive uri in IE6-9 for anonymous modules if ( !isWebWorker && !meta.uri && doc.attachEvent && typeof getCurrentScript !== "undefined" ) { var script = getCurrentScript();
if (script) { meta.uri = script.src; }
// NOTE: If the id-deriving methods above is failed, then falls back // to use onload event to get the uri }
// Emit `define` event, used in nocache plugin, seajs node version etc emit("define", meta);
meta.uri ? Module.save(meta.uri, meta) : // Save information for "saving" work in the script onload event (anonymousMeta = meta); };
Module.save = function (uri, meta) { var mod = Module.get(uri);
// Do NOT override already saved modules if (mod.status < STATUS.SAVED) { mod.id = meta.id || uri; mod.dependencies = meta.deps || []; mod.factory = meta.factory; mod.status = STATUS.SAVED;
emit("save", mod); } };
Module.get
1 2 3
Module.get = function (uri, deps) { return cachedMods[uri] || (cachedMods[uri] = new Module(uri, deps)); };
Module.resolve
1 2 3 4 5 6 7 8
// Resolve id to uri Module.resolve = function (id, refUri) { // Emit `resolve` event for plugins such as text plugin var emitData = { id: id, refUri: refUri }; emit("resolve", emitData);
// Send all requests at last to avoid cache bug in IE6-9. Issues#808 for (var requestUri in requestCache) { if (requestCache.hasOwnProperty(requestUri)) { requestCache[requestUri](); } } };
Module.prototype.pass = function () { var mod = this;
var len = mod.dependencies.length;
for (var i = 0; i < mod._entry.length; i++) { var entry = mod._entry[i]; var count = 0; for (var j = 0; j < len; j++) { var m = mod.deps[mod.dependencies[j]]; // If the module is unload and unused in the entry, pass entry to it if (m.status < STATUS.LOADED && !entry.history.hasOwnProperty(m.uri)) { entry.history[m.uri] = true; count++; m._entry.push(entry); if (m.status === STATUS.LOADING) { m.pass(); } } } // If has passed the entry to it's dependencies, modify the entry's count and del it in the module if (count > 0) { entry.remain += count - 1; mod._entry.shift(); i--; } } };
// Call this method when module is loaded Module.prototype.onload = function () { var mod = this; mod.status = STATUS.LOADED;
// When sometimes cached in IE, exec will occur before onload, make sure len is an number for (var i = 0, len = (mod._entry || []).length; i < len; i++) { var entry = mod._entry[i]; if (--entry.remain === 0) { entry.callback(); } }
delete mod._entry; };
将 mod 的 status 变成 STATUS.LOADED。在 mod.remain 为 1 时,也就是只有 mod 自己时,执行 mod.callback
Module.prototype.exec = function () { var mod = this;
// When module is executed, DO NOT execute it again. When module // is being executed, just return `module.exports` too, for avoiding // circularly calling if (mod.status >= STATUS.EXECUTING) { return mod.exports; }
mod.status = STATUS.EXECUTING;
if (mod._entry && !mod._entry.length) { delete mod._entry; }
//non-cmd module has no property factory and exports if (!mod.hasOwnProperty("factory")) { mod.non = true; return; }
// Create require var uri = mod.uri;
functionrequire(id) { var m = mod.deps[id] || Module.get(require.resolve(id)); if (m.status == STATUS.ERROR) { thrownewError("module was broken: " + m.uri); } return m.exec(); }
require.resolve = function (id) { return Module.resolve(id, uri); };
require.async = function (ids, callback) { Module.use(ids, callback, uri + "_async_" + cid()); returnrequire; };
// Fetch a module Module.prototype.fetch = function (requestCache) { var mod = this; var uri = mod.uri;
mod.status = STATUS.FETCHING;
// Emit `fetch` event for plugins such as combo plugin var emitData = { uri: uri }; emit("fetch", emitData); var requestUri = emitData.requestUri || uri;
// Empty uri or a non-CMD module if (!requestUri || fetchedList.hasOwnProperty(requestUri)) { mod.load(); return; }
if (fetchingList.hasOwnProperty(requestUri)) { callbackList[requestUri].push(mod); return; }
// Save meta data of anonymous module if (anonymousMeta) { Module.save(uri, anonymousMeta); anonymousMeta = null; }
// Call callbacks var m, mods = callbackList[requestUri]; delete callbackList[requestUri]; while ((m = mods.shift())) { // When 404 occurs, the params error will be true if (error === true) { m.error(); } else { m.load(); } } } };