The asynchronous module mode AMD
is to continue other business logic after the request is issued until the module is loaded and the subsequent logic is executed to realize the reference to the module after the module is loaded in module development. The famous require.js
is based on this idea Yes, the asynchronous module pattern does not belong to the generally defined 23
design patterns, but is usually regarded as an architectural design pattern in a broad sense.
The asynchronous module mode is mainly used in the browser environment. The browser environment is different from the server environment. In order not to block the rendering thread, external Js
files are usually loaded asynchronously, so some module methods in the file must be used. After going through the file loading process, the synchronous module mode cannot be applied to this problem, and the asynchronous module mode needs to be used. The asynchronous module mode not only reduces the problem of variables and method names being overwritten during multi-person development, but also increases module dependencies, so that developers do not have to worry about unusable problems caused by some methods not being loaded or not being loaded. Some functions are loaded asynchronously You can also strip out more unnecessary functions on the first screen to reduce the cost of loading the first screen.
// dom.js
F.module("./dom", function() {
return {
g: function(id) {
return document.getElementById(id);
},
html: function(id, html) {
if (!html) return this.g(id).innerHTML;
else this.g(id).innerHTML = html;
}
}
});
// event.js
F.module("./event", ["./dom"], function(dom) {
return {
on: function(id, type, fn) {
dom.g(id)["on" + type] = fn;
}
}
});
<!-- demo.html -->
<!DOCTYPE html>
<html>
<head>
<title>Asynchronous module pattern</title>
</head>
<body>
<div id="demo">Click Me</div>
</body>
<script type="text/javascript">
(function(F) {
const moduleCache = {};
function getUrl(moduleName) {
return String(moduleName).replace(/\.js$/g, "") + ".js"
}
function loadScript(src) {
let _script = document.createElement("script");
_script.type = "text/javascript";
_script.charset = "UTF-8";
_script.async = true;
_script.src = src;
document.body.appendChild(_script);
}
function setModule(moduleName, params, callback) {
let _module = null, fn = null;
if(moduleCache[moduleName]) {
_module = moduleCache[moduleName];
_module.status = "loaded";
_module.exports = callback ? callback.apply(_module, params) : null;
while (fn = _module.onload.shift()) {
fn(_module.exports)
}
} else {
callback && callback.apply(null, params);
}
}
function loadModule(moduleName, callback) {
let _module = "";
if (moduleCache[moduleName]) {
_module = moduleCache[moduleName];
if (_module.status === "loaded") {
// This is very important. loadModule must be asynchronous. A certain suggestion on effectiveJS states that you should never call asynchronous functions synchronously. This is very important.
setTimeout(callback(_module.exports), 0);
} else {
// Called when loading is complete
_module.onload.push(callback);
}
} else {
// first load
moduleCache[moduleName] = {
moduleName: moduleName,
status: "loading",
exports: null,
onload: [callback]
};
loadScript(getUrl(moduleName));
}
}
F.module = function(...args) {
// Get the module constructor (the last parameter member in the parameter array)
let callback = args.pop();
// Get the dependent module (next to the callback function parameters, and the data type is an array)
let deps = (args.length && args[args.length - 1] instanceof Array) ? args.pop() : [];
// The module url (module ID)
let url = args.length ? args.pop() : null;
// Dependency module sequence
let params = [];
// Statistics on the number of unloaded dependent modules
let depsCount = 0;
if(deps.length) {
deps.forEach((v ,i) => {
// Increase the number of unloaded dependent modules statistics
depsCount++;
// Load dependent modules asynchronously
loadModule(deps[i], function(mod) {
// The number of dependent modules added in the dependent module sequence will be reduced by one.
depsCount--;
params[i] = mod;
// If all dependent modules are loaded
if(depsCount === 0) {
// Align the module in the module cache and execute the constructor
setModule(url, params, callback);
}
});
})
} else { // No dependent modules, directly execute the callback function
// Align the module in the module cache and execute the constructor
setModule(url, [], callback);
}
}
})((() => window.F = ({}))());
F.module(["./event", "./dom"], function(events, dom) {
console.log(events, dom)
events.on("demo", "click", function() {
dom.html("demo", "success");
})
});
</script>
</html>
https://github.com/WindrunnerMax/EveryDay
https://www.jianshu.com/p/d71fc902051e
https://blog.csdn.net/WuLex/article/details/107350493
https://blog.csdn.net/a545415/article/details/77930534