【问题标题】:Delay a script from running until all assets have loaded延迟脚本运行,直到所有资产都加载完毕
【发布时间】:2012-11-21 19:00:50
【问题描述】:

简要说明

这并不像听起来那么基本,所以在你阅读并理解我想要做的事情之前,请不要跳到回答:-)。

我有一个名为 SineMacula 的对象,其中包含一些类似这样的基本函数(暂时忽略 ready 函数):

(function(global, $){

    // MOST CODE STRIPT OUT HERE */

    /**
     * Sine Macula Run
     * Makes it easy to write plugins for the Sine Macula library
     *
     * @param function callback
     */
    SM.run = run;
    function run(callback){
        // Call the function with the Sine Macula
        // and jQuery objects
        callback(SM, $);
    }

    /**
     * Sine Macula Ready
     * Executes code once the Sine Macula and jQuery
     * libraries are ready
     *
     * @param function callback
     */
    SM.ready = ready;
    function ready(callback){
        // Call the function with the Sine Macula
        // and jQuery objects
        jQuery(function($) {
            callback(SM, $);
        });
    }

    /**
     * Sine Macula Load
     * Load the Sine Macula Libraries and Plugins
     * into the current document
     *
     * The options:
     * - package: the package of libraries to load
     * - packageURL: a remote source to load the package details from
     * - libraries: any additional libraries to load
     *
     * @param object parameter The options for the Sine Macula load
     */
    SM.load = load;
    function load(options){
        // BUILD A QUERY HERE
        // ...
        // Complete the url by appending the query
        url = '//libraries.sinemaculammviii.com/'+query;        
        // Append the script tag to the end of the document
        script = document.createElement('script');
        script.type = 'text/javascript';
        script.src = url;
        $('head')[0].appendChild(script);       
    }
})(this, this.jQuery);

load() 函数通过将相关脚本标记附加到页面的 head 来简单地加载页面的所有相关插件/库。

加载页面中的所有脚本都作为调用run 的函数的回调运行。这可确保 jQuerySineMacula 都被传递给插件。

问题

这就是问题所在,因为库正在加载到SineMacula 对象中,无法检测它们是否已加载。

例如,如果其中一个库包含一个名为 setDate() 的函数插件,我运行:

SM.setDate()

这不一定有效,因为 setDate() 函数可能尚未加载到 SineMacula 对象中,因此它将返回“未捕获的 TypeError...”。

任何人都可以建议对SineMacula.ready() 函数进行良好的调整以检测库是否存在?

请不要对jQuery.load()函数提出建议,我很清楚。

我不希望解决方案是函数load() 的回调,除非绝对必要。

我希望这是有道理的,如果不让我知道,我会发布更多信息。希望尽可能简短。

提前致谢

更新

忘了提到我有一个测试页面here,您可以在其中看到我遇到的错误并更好地了解我在做什么:-)

【问题讨论】:

  • @AbdullahJibaly 我愿意 :-) 如果您想在测试页面上查看错误,请转到 libraries.sinemaculammviii.com/test.php
  • 为什么要使用操作 DOM 来创建脚本元素而不是使用 jQuery?
  • @Rob 只是因为 jQuery 在 script 标签中添加了一些奇怪的属性。想要恢复到 jQuery,但不确定属性做了什么。类似async

标签: javascript jquery sinemacula


【解决方案1】:

如果我理解正确,是用户从他们的脚本中调用SM.run(),然后调用SM.load(),后者加载库的其他部分。

因此,如果是这种情况,那么无论如何,他们的脚本将在加载库的任何其他部分之前完成执行。

我认为您需要做的是要求用户将其.run() 与其余代码放在一个单独的脚本中。然后您可以使用document.write 加载其他脚本。这将导致他们加载并阻止下一个脚本,该脚本将包含用户的其余代码:

function load(options){
    // BUILD A QUERY HERE
    // ...
    // Complete the url by appending the query
    document.write('<scr' + 'ipt type="text/javascript" ',
                            ' src="//libraries.sinemaculammviii.com/' + query,
                            '"><\/scr' + 'ipt>');      
}

<script type="text/javascript" src="/path/to/your/lib.js"></script>
<script type="text/javascript">
    SineMacula.load('all');
</script>

<!-- The document.write will write the new script here, and it will be loaded
         syncronously, so it will block. -->

<script type="text/javascript">
    // code that uses the loaded library parts
</script>

【讨论】:

  • 请不要推荐使用document.write
  • @AbdullahJibaly:为什么,在这种情况下它是一个非常有用的工具。
  • 请查看我的编辑,因为我发布了一个可能会改变您的答案的链接。当您看到页面的结构时会更容易理解:-)
  • @user1689607 您将无法在脚本中找到SM.run,因为该特定脚本已被缩小,但要回答您的问题,不会从run() 中调用负载
  • "在浏览器继续解析页面之前,会立即获取并执行没有 async 或 defer 属性的脚本。"
【解决方案2】:

由于缺少某些上下文,不确定我是否在回答您的问题,但您可能想使用Deferreds:

SM.ready = ready;
function ready(callback){
    var deferred = $.Deferred();
    // Call the function with the Sine Macula
    // and jQuery objects
    jQuery(function($) {
        deferred.resolve();
        if (typeof(callback) === "function") {
            callback(SM, $);
        }
    });
    return deferred;
}

现在您可以执行以下操作:

SM.ready().done(function() {
    // everything is now set.
});

【讨论】:

    猜你喜欢
    • 2023-03-28
    • 2011-09-15
    • 2010-11-03
    • 1970-01-01
    • 2011-11-18
    • 1970-01-01
    • 1970-01-01
    • 2019-02-24
    • 2017-07-20
    相关资源
    最近更新 更多