Skip to content

Instantly share code, notes, and snippets.

@thomaswilburn
Last active March 10, 2017 00:30
Show Gist options
  • Save thomaswilburn/64e28c5d894acc92ad24541f9fbf7bf2 to your computer and use it in GitHub Desktop.
Save thomaswilburn/64e28c5d894acc92ad24541f9fbf7bf2 to your computer and use it in GitHub Desktop.
AMD promises

Promises make it easy to express a asynchronous dependency tree - combined with await/async, we can effectively write an AMD-style require() and define() in only a few lines of code. In this demo, main.js loads a.js, which in turn requires b.js. With async functions, the first module will naturally pause for its dependency to resolve before it continues loaded, a nice CommonJS-like behavior that doesn't require pausing the event loop.

One caution is that if a module requires many other modules, it's a bad idea to await them all in sequence, since each dependency would have to wait for the previous dependency to load and execute before it begins loading itself. Instead, use Promise.all() to wrap up the dependencies, and then destructuring to unpack them:

define(async function() {

  //these requests fire simultaneously
  var [a, b, c] = await Promise.all([ require("a"), require("b"), require("c") ]);
  //this code won't run until all have resolved in any order
  console.log(a, b, c); 

});
define(async function() {
console.log("a loaded");
var b = await require("b.js");
return { a: true, b };
});
define(function() {
console.log("b loaded");
return { b: true };
});
//let's define our own module system, why not
(function() {
var modules = {};
var requests = {};
window.require = function(url) {
if (modules[url]) return modules[url];
if (!requests[url]) requests[url] = new Promise(function(ok, fail) {
var script = document.createElement("script");
script.src = url;
document.body.appendChild(script);
script.onload = () => ok();
script.onerror = fail;
});
return requests[url].then(() => modules[url]);
};
window.define = function(module) {
var script = document.currentScript;
if (typeof module == "function") module = module();
modules[script.getAttribute("src")] = Promise.resolve(module);
};
})();
(async function() {
// collect modules with await
var [a, b] = await Promise.all([require("a.js"), require("b.js")]);
console.log(a);
})();
//or just require them and use Promises directly
require("b.js").then(val => console.log("b", val));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment