1. ホーム
  2. javascript

[解決済み] 非同期でスクリプトを読み込む

2022-06-25 13:56:56

質問

私はいくつかのプラグイン、カスタムウィジェット、JQueryからの他のライブラリを使っています。その結果、いくつかの.jsと.cssファイルがあります。読み込みに時間がかかるので、私のサイトのローダーを作成する必要があります。すべてのファイルをインポートする前にローダーを表示することができれば、それは素晴らしいでしょう。

<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ライブラリを非同期でインポートするためのチュートリアルをいくつか見つけました。

  (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関数が他の関数に依存しているからだろうと思った。しかし、私は1つが完了したときにタイムアウト機能を使用して正しい順序でそれらをロードし、私は次のページに進み、ページはまだ奇妙な動作をする。

とにかく

私が考えていることは、次のとおりです... 私はブラウザがキャッシュを持っていると信じています、それは最初のページをロードするのに長い時間がかかり、次の時間は速い理由です。ajaxがこれらのファイルをすべてロードし終わると、私が使う予定のページにリダイレクトします。そのページを使うとき、ファイルはすでにブラウザのキャッシュに含まれているはずなので、ロードに長くはかからないはずです。私はローダーを表示し、完了したときにページをリダイレクトするだけです...

このアイデアは良い代替案でしょうか?それとも、非同期メソッドの実装に挑戦し続けるべきでしょうか?


EDIT

非同期で読み込む方法は、こんな感じです。

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の関数があります。

どのように解決するのですか?

非同期ロードのためのいくつかの解決策。

//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を搭載している場合はそのまま使用します。

$.getScript(url, successCallback) *

さらに、ドキュメントの読み込みが完了する前にスクリプトが読み込まれたり実行されたりする可能性があります。 document.ready を待つ必要があるということです。

コードを見ないと、あなたの問題が何であるかを具体的に説明することはできません。

最も簡単な解決策は、ページの下部にあるすべてのスクリプトをインラインで維持することです。また、必要な各スクリプトを非同期に読み込まなければならないという問題も回避できます。

常に使用されるわけではないが、ある種の大きなスクリプトを必要とする特に派手なインタラクションがある場合、必要になるまでその特定のスクリプトをロードしないようにすると便利です(レイジーローディング)。

* で読み込まれるスクリプト $.getScript でロードされたスクリプトは、おそらくキャッシュされないでしょう。


のような現代的な機能を使える人にとっては、このような Promise オブジェクトを使用すると loadScript 関数が大幅に簡素化されました。

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 引数は受け付けないことに注意してください。以前は loadScript(src, callback) であったものが loadScript(src).then(callback) .

これには、失敗を検出して処理することができるという利点があります。例えば、...

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

...そして、CDNの停止を優雅に扱うことができます。