Javascript es5 async plugin architecture

I am trying to figure out a way to structure a new structure for work that is capable of introducing plugins. The idea is for each file to be loaded asynchronously.

Here is how I would like to configure my plugins:

<script id="target_root" src="assets/js/target/target.js" async="true"></script> <script> var target = target || {}; target.cmd = target.cmd || []; target.cmd.push(function () { target.loadPlugins([ {"name": "root", "src": "assets/js/target/target.root.js"}, {"name": "krux", "src": "assets/js/target/target.krux.js"} ]).then( target.init([ { 'plugin': 'root', 'opts': { 'foo': 'bar' } }, { 'plugin': 'krux', 'opts': { 'foo': 'bar' } } ]) ) }); </script> 

As I would use the built-in functions (inside the DOM), I was thinking about using a command queue that, when loaded, will call all the pressed functions (a bit like cmd DFP).

As indicated above, each plugin will be loaded asynchronously, so the initialization of each of them should begin only when all of them are loaded (therefore, the then () function).

Here I have a script:

 var target = (function(root, w, d, c) { var queueIndex = 0, amountPluginsLoaded = 0, pluginsLoaded = []; root.cmd = { 'queue': root && root.cmd ? root.cmd : [], 'push': function(fn) { this.queue.push(fn); this.next(); }, 'next': function() { if (this.queue.length > 0) { this.queue.shift()(); } } }; root.init = function(plugins) { }; root.loadPlugins = function(plugins) { var i = 0, len = plugins.length; for(; i < len; i++) { _loadExternalJS(plugins[i]); } }; function _loadExternalJS(plugin) { var scriptRoot = d.getElementById('target_root'), scriptElement = d.createElement('script'); scriptElement.setAttribute('type', 'text/javascript'); scriptElement.setAttribute('async', 'true'); scriptElement.onload = function() { amountPluginsLoaded++; pluginsLoaded.push(plugin.name); }; scriptElement.setAttribute('src', plugin.src); scriptRoot.parentNode.insertBefore(scriptElement, scriptRoot.nextSibling); } function _initPlugin(plugin) { } for (; queueIndex < root.cmd.queue.length; queueIndex++) { root.cmd.next(); } }(target || {}, window, document, console)); 

Here you have the basic function cmd, which will be overridden and load each of the scripts.

What I seem to be unable to understand is how to run if (). I suppose you will track it in _loadExternalJS () in the onload event (as you can see in the code). But just adding if (amountPluginsLoaded === pluginsLoaded.length) {fire all inits} seems unproductive and not what the function belongs to. so I would like to implement some then () function.

Any ideas / opinions?

+7
javascript asynchronous plugins
source share
2 answers

Since I did not receive a valid answer, I accepted my ill-conceived idea: (

 function _loadExternalJS(elem) { var scriptRoot = d.getElementById('target_root'), scriptElement = d.createElement('script'), isElemPlugin = elem.isPlugin || typeof elem.isPlugin === "undefined", loadAsync = elem.async || typeof elem.async === "undefined"; scriptElement.setAttribute('type', 'text/javascript'); scriptElement.setAttribute('async', loadAsync); if (isElemPlugin) { scriptElement.onload = function() { jsLoaded++; }; } scriptElement.setAttribute('src', elem.src); scriptRoot.parentNode.insertBefore(scriptElement, scriptRoot.nextSibling); } 

For those who are wondering about the β€œnext” functionality, I did the following:

 target.init = function (plugins) { //do something return { 'then': _then } }; function _then(fn) { var loaded; loaded = w.setInterval(function () { if (jsLoaded === pluginList.length) { w.clearInterval(loaded); fn(); } }, 10); } 

If any of you have a better idea, please write !!!! :)

0
source share

You can use promise and prom.all to check if they are all loaded.

 root.loadPlugins = function(plugins) { var promiseArray = plugins.map(function(plugin){ return _loadExternalJS(plugin); }); return Promise.all(promiseArray); }; function _loadExternalJS(plugin) { return new Promise((resolve, reject) => { var scriptRoot = d.getElementById('target_root'), scriptElement = d.createElement('script'); scriptElement.setAttribute('type', 'text/javascript'); scriptElement.setAttribute('async', 'true'); scriptElement.onload = function() { amountPluginsLoaded++; pluginsLoaded.push(plugin.name); resolve(plugin.name); }; scriptElement.setAttribute('src', plugin.src); scriptRoot.parentNode.insertBefore(scriptElement, scriptRoot.nextSibling); }); } 

then

 root.loadPlugins().then(function(){ //initialize plugins }); 
+2
source share

All Articles