From 7b91e2a608a25480c59ca1c6974d55d0939f83ac Mon Sep 17 00:00:00 2001 From: Tim Martin Date: Sun, 23 Sep 2018 16:01:03 -0400 Subject: [PATCH] Add a promise-driven initAsync method Allows the loading of resources (such as web assembly modules) before initializing Crafty. --- src/core/core.js | 67 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) diff --git a/src/core/core.js b/src/core/core.js index 696fe756..18ad4a4c 100644 --- a/src/core/core.js +++ b/src/core/core.js @@ -1384,6 +1384,7 @@ Crafty._addCallbackMethods(Crafty); Crafty.extend({ // Define Crafty's id 0: "global", + /**@ * #Crafty.init * @category Core @@ -1426,6 +1427,72 @@ Crafty.extend({ return this; }, + // async_resources is an array of promises, or functions that return a promise. + // In the latter case, functions are passed the Crafty object as a parameter. + // In addition to the specified promises, also wait for the document to load + // That'll be added at the end of the promise array + // + // Once complete it will call Crafty.init with w, h, stage_elem, and then finally + // resolve a promise with the values of the promise array + + /**@ + * #Crafty.initAsync + * @category Core + * @kind Method + * + * @trigger Load - Just after the viewport is initialised. Before the UpdateFrame loops is started + * @sign public this Crafty.initAsync([Array loaders], [Number width, Number height, String stage_elem]) + * @param Array loaders An array that can contain a mix of Promises, or functions that Promises + * @param Number width - Width of the stage + * @param Number height - Height of the stage + * @param String or HTMLElement stage_elem - the element to use for the stage + * + * A version of Crafty.init that uses Promises to load any needed resources before initialization. + * + * The first argument is an array of either Promises, or functions that return promises. + * In the second case, a Promise will be generated by invoking the function with the current Crafty instance as an argument. + * (The array can be a mixture of the two types.) + * + * Once all promises are ready, and the document itself has loaded, Crafty.init will be invoked with the `w`, `h`, and `stage_elem` arguments. + * + * The method returns a Promise whose fufillment is an array of each passed promises fufillment, + * and whose rejection is the rejection of the first promise to fail. (Essentially the same as Promise.all) + * + * @see Crafty.init + */ + initAsync: function(loaders, w, h, stage_elem) { + // first argument is optional + if (typeof loaders !== "object") { + stage_elem = h; + h = w; + w = loaders; + loaders = []; + } + + var promises = []; + for (var i in loaders) { + if (typeof loaders[i] === "function") { + promises.push(loaders[i](Crafty)); + } else { + promises.push(loaders[i]); + } + } + + // wait for document loading if necessary + if (document.readyState !== "complete") { + var window_load = new Promise(function(resolve, reject) { + window.onload = resolve; + promises.push(window_load); + }); + } + + return Promise.all(promises).then(function(values) { + Crafty.init(w, h, stage_elem); + // Return results only for promises passed in with the loaders array + return values.slice(0, loaders.length); + }); + }, + // There are some events that need to be bound to Crafty when it's started/restarted, so store them here // Switching Crafty's internals to use the new system idiom should allow removing this hack _bindOnInit: [],