异步加载脚本 [英] load scripts asynchronously

查看:27
本文介绍了异步加载脚本的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 JQuery 中的几个插件、自定义小部件和其他一些库.结果我有几个 .js 和 .css 文件.我需要为我的网站创建一个加载器,因为加载需要一些时间.如果我可以在导入所有内容之前显示加载程序,那就太好了:

I am using several plugins, custom widgets and some other libraries from JQuery. as a result I have several .js and .css files. I need to create a loader for my site because it takes some time to load. it will be nice if I can display the loader before importing all the:

<script type="text/javascript" src="js/jquery-1.6.2.min.js"></script>
<script type="text/javascript" src="js/myFunctions.js"></script>
<link type="text/css" href="css/main.css" rel="stylesheet" />
... 
....
 etc

我找到了几个教程,可以让我异步导入 JavaScript 库.例如,我可以执行以下操作:

I have found several tutorials that enable me to import a JavaScript library asynchronously. for example I can do something like:

  (function () {
        var s = document.createElement('script');
        s.type = 'text/javascript';
        s.async = true;
        s.src = 'js/jquery-ui-1.8.16.custom.min.js';
        var x = document.getElementsByTagName('script')[0];
        x.parentNode.insertBefore(s, x);
    })();

出于某种原因,当我对所有文件执行相同操作时,页面不起作用.我已经尝试了很长时间试图找到问题所在,但我就是找不到它.首先我认为这可能是因为某些 javascript 函数依赖于其他函数.但是当一个完成时我使用超时功能以正确的顺序加载它们我继续下一个并且页面仍然表现得很奇怪.例如,我无法点击链接等...动画仍然有效...

for some reason when I do the same thing for all my files the pages does not work. I have been trying for so long to try to find where the problem is but I just cannot find it. First I thought that it was probably because some javascript functions depended on the others. but I loaded them in the right order using the time out function when one completed I proceeded with the next and the page still behaves weird. for example I am not able to click on links etc... animations still work though..

这就是我一直在想的……我相信浏览器有一个缓存,这就是为什么第一次加载页面需要很长时间,而下一次加载很快.所以我想做的是用异步加载所有这些文件的页面替换我的 index.html 页面.当 ajax 完成加载所有这些文件时,重定向到我打算使用的页面.使用该页面时,加载时间应该不会太长,因为这些文件应该已经包含在浏览器的缓存中.在我的索引页(.js 和 .css 文件被异步加载的页面)上,我不在乎出现错误.我将只显示一个加载程序并在完成后重定向页面...

Here is what I have been thinking... I believe browsers have a cache that's why it takes a long time to load the page for the first time and the next time it is quick. so what I am thinking of doing is replacing my index.html page with a page that loads all this files asynchronously. when ajax is done loading all those files redirect to the page that I plan on using. when using that page it should not take long to load since the files should alredy be included on the cache of the browser. on my index page (page where .js and .css file get loaded asynchronously) I don't care of getting errors. I will just be displaying a loader and redirecting the page when done...

这个想法是一个不错的选择吗?还是应该继续尝试实现异步方法?

Is this idea a good alternative? or should I keep trying on implementing the asynchronously methods?

我异步加载所有内容的方式如下:

the way I load everything async is like:

importScripts();

function importScripts()
{
    //import: jquery-ui-1.8.16.custom.min.js
    getContent("js/jquery-1.6.2.min.js",function (code) {
                var s = document.createElement('script');
                s.type = 'text/javascript';
                //s.async = true;
                s.innerHTML=code;
                var x = document.getElementsByTagName('script')[0];
                x.parentNode.insertBefore(s, x);
                setTimeout(insertNext1,1);
            });


    //import: jquery-ui-1.8.16.custom.min.js
    function insertNext1()
    {
        getContent("js/jquery-ui-1.8.16.custom.min.js",function (code) {
                    var s = document.createElement('script');
                    s.type = 'text/javascript';
                    s.innerHTML=code;
                    var x = document.getElementsByTagName('script')[0];
                    x.parentNode.insertBefore(s, x);
                    setTimeout(insertNext2,1);
                });
    }

    //import: jquery-ui-1.8.16.custom.css
    function insertNext2()
    {

        getContent("css/custom-theme/jquery-ui-1.8.16.custom.css",function (code) {
                    var s = document.createElement('link');
                    s.type = 'text/css';
                    s.rel ="stylesheet";
                    s.innerHTML=code;
                    var x = document.getElementsByTagName('script')[0];
                    x.parentNode.insertBefore(s, x);
                    setTimeout(insertNext3,1);
                });
    }

    //import: main.css
    function insertNext3()
    {

        getContent("css/main.css",function (code) {
                    var s = document.createElement('link');
                    s.type = 'text/css';
                    s.rel ="stylesheet";
                    s.innerHTML=code;
                    var x = document.getElementsByTagName('script')[0];
                    x.parentNode.insertBefore(s, x);
                    setTimeout(insertNext4,1);
                });
    }

    //import: jquery.imgpreload.min.js
    function insertNext4()
    {
        getContent("js/farinspace/jquery.imgpreload.min.js",function (code) {
                    var s = document.createElement('script');
                    s.type = 'text/javascript';
                    s.innerHTML=code;
                    var x = document.getElementsByTagName('script')[0];
                    x.parentNode.insertBefore(s, x);
                    setTimeout(insertNext5,1);
                });
    }


    //import: marquee.js
    function insertNext5()
    {
        getContent("js/marquee.js",function (code) {
                    var s = document.createElement('script');
                    s.type = 'text/javascript';
                    s.innerHTML=code;
                    var x = document.getElementsByTagName('script')[0];
                    x.parentNode.insertBefore(s, x);
                    setTimeout(insertNext6,1);
                });
    }


    //import: marquee.css
    function insertNext6()
    {

        getContent("css/marquee.css",function (code) {
                    var s = document.createElement('link');
                    s.type = 'text/css';
                    s.rel ="stylesheet";
                    s.innerHTML=code;
                    var x = document.getElementsByTagName('script')[0];
                    x.parentNode.insertBefore(s, x);
                    setTimeout(insertNext,1);
                });
    }



    function insertNext()
    {
        setTimeout(pageReadyMan,10);        
    }
}


// get the content of url and pass that content to specified function
function getContent( url, callBackFunction )
{
     // attempt to create the XMLHttpRequest and make the request
     try
     {
        var asyncRequest; // variable to hold XMLHttpRequest object
        asyncRequest = new XMLHttpRequest(); // create request object

        // register event handler
        asyncRequest.onreadystatechange = function(){
            stateChange(asyncRequest, callBackFunction);
        } 
        asyncRequest.open( 'GET', url, true ); // prepare the request
        asyncRequest.send( null ); // send the request
     } // end try
     catch ( exception )
     {
        alert( 'Request failed.' );
     } // end catch
} // end function getContent

// call function whith content when ready
function stateChange(asyncRequest, callBackFunction)
{
     if ( asyncRequest.readyState == 4 && asyncRequest.status == 200 )
     {
           callBackFunction(asyncRequest.responseText);
     } // end if
} // end function stateChange

奇怪的部分是所有样式的工作加上所有 javascript 功能.页面由于某种原因被冻结...

and the weird part is that all the style's work plus all the javascript functions. the page is frozen for some reason though...

推荐答案

异步加载的几个解决方案:

A couple solutions for async loading:

//this function will work cross-browser for loading scripts asynchronously
function loadScript(src, callback)
{
  var s,
      r,
      t;
  r = false;
  s = document.createElement('script');
  s.type = 'text/javascript';
  s.src = src;
  s.onload = s.onreadystatechange = function() {
    //console.log( this.readyState ); //uncomment this line to see which ready states are called.
    if ( !r && (!this.readyState || this.readyState == 'complete') )
    {
      r = true;
      callback();
    }
  };
  t = document.getElementsByTagName('script')[0];
  t.parentNode.insertBefore(s, t);
}

如果页面上已经有 jQuery,只需使用:

If you've already got jQuery on the page, just use:

$.getScript(url, successCallback)*

此外,您的脚本可能在文档加载完成之前被加载/执行,这意味着您需要等待 document.ready 事件才能绑定到元素.

Additionally, it's possible that your scripts are being loaded/executed before the document is done loading, meaning that you'd need to wait for document.ready before events can be bound to the elements.

如果不查看代码,就无法具体说明您的问题是什么.

It's not possible to tell specifically what your issue is without seeing the code.

最简单的解决方案是将所有脚本内嵌在页面底部,这样它们在执行时就不会阻止加载 HTML 内容.它还避免了必须异步加载每个所需脚本的问题.

The simplest solution is to keep all of your scripts inline at the bottom of the page, that way they don't block the loading of HTML content while they execute. It also avoids the issue of having to asynchronously load each required script.

如果您有一个并不总是使用的特别花哨的交互,需要某种更大的脚本,那么避免在需要之前加载该特定脚本(延迟加载)可能会很有用.

If you have a particularly fancy interaction that isn't always used that requires a larger script of some sort, it could be useful to avoid loading that particular script until it's needed (lazy loading).

* 加载了 $.getScript 的脚本可能不会被缓存

* scripts loaded with $.getScript will likely not be cached

对于可以使用现代功能的任何人,例如 Promise 对象,loadScript 函数变得非常简单:

For anyone who can use modern features such as the Promise object, the loadScript function has become significantly simpler:

function loadScript(src) {
    return new Promise(function (resolve, reject) {
        var s;
        s = document.createElement('script');
        s.src = src;
        s.onload = resolve;
        s.onerror = reject;
        document.head.appendChild(s);
    });
}

请注意,此版本不再接受 callback 参数,因为返回的 Promise 将处理回调.以前是 loadScript(src, callback) 现在是 loadScript(src).then(callback).

Be aware that this version no longer accepts a callback argument as the returned promise will handle callback. What previously would have been loadScript(src, callback) would now be loadScript(src).then(callback).

这具有能够检测和处理故障的额外好处,例如可以调用...

This has the added bonus of being able to detect and handle failures, for example one could call...

loadScript(cdnSource)
    .catch(loadScript.bind(null, localSource))
    .then(successCallback, failureCallback);

...它会优雅地处理 CDN 中断.

...and it would handle CDN outages gracefully.

这篇关于异步加载脚本的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆