首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >javascript es5异步插件架构

javascript es5异步插件架构
EN

Stack Overflow用户
提问于 2017-06-23 22:41:24
回答 2查看 203关注 0票数 7

我正在试图找出一种方法来构建一个能够注入插件的新工作框架。其思想是让每个文件异步加载。

下面是我希望如何配置我的插件:

代码语言:javascript
复制
<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>

因为我要使用内联函数(在DOM中),所以我想使用一个命令队列,它在加载时将调用所有推送函数(有点像DFP的googletag cmd )。

如前所述,每个插件都是异步加载的,因此每个插件的初始化应该只在所有插件都加载后才开始(因此使用then()函数)。

下面是我的脚本:

代码语言:javascript
复制
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));

在这里,您有基本的cmd功能,它将被覆盖,并加载每个脚本。

我似乎不能理解的是如何启动then()。我想您应该在它的onload事件的_loadExternalJS()中跟踪它(正如您在代码中看到的那样)。但是简单地添加一个if(amountPluginsLoaded === pluginsLoaded.length) { fire all inits }似乎没有效率,而且不属于该函数。这就是为什么我喜欢实现一些then()特性的原因。

有什么想法/意见吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-07-03 22:14:46

由于我没有收到有效的答案,我接受了我的无效想法:(

代码语言:javascript
复制
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);
}

对于那些想知道"then“功能的人,我做了以下工作:

代码语言:javascript
复制
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);
}

如果你有更好的想法,请发帖子!:)

票数 0
EN

Stack Overflow用户

发布于 2017-06-27 01:43:02

您可以使用promisepromise.all来检查它们是否都已加载。

代码语言:javascript
复制
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);
   });
}

然后

代码语言:javascript
复制
root.loadPlugins().then(function(){
    //initialize plugins
});
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/44724164

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档