2012-03-14 30 views
9

でのロード・スクリプトは、私はjQueryを使っていくつかのスクリプトを動的負荷をしようとしている:時々jQueryの:順序

var scripts = ['script1.js','script2.js','script3.js']; 

$.each(scripts , function(i, val) { 
    $.getScript(val, function() { 
    console.log('loaded '+ val); 
}); 

しかし、ロードされたスクリプトの変更の順​​序を。前のスクリプトが正常に読み込まれた後に、各スクリプトをロードするにはどうすればよいですか?

答えて

16

コールバック関数$.getScript()を再帰関数呼び出しとして使用して、前回のロードが完了した後にそれぞれをロードできます。あなたのコードで発生しています何

//setup array of scripts and an index to keep track of where we are in the process 
var scripts = ['script1.js','script2.js','script3.js'], 
    index = 0; 

//setup a function that loads a single script 
function load_script() { 

    //make sure the current index is still a part of the array 
    if (index < scripts.length) { 

     //get the script at the current index 
     $.getScript(scripts[index], function() { 

      //once the script is loaded, increase the index and attempt to load the next script 
      console.log('Loaded: ' + scripts[index]); 
      index++; 
      load_script(); 
     }); 
    } 
} 

は、スクリプトが同時に要求されていることであり、彼らは非同期ロード以来、彼らが戻ってランダムな順序で実行されます。

それらはすべてがにロードされるまで、変数のコードのすべてを格納し、その後、私はこれをテストしていませんが、スクリプトがローカルでホストされている場合、あなたはプレーンテキストでそれらを取得しようとすることができます更新

時間は、あなたが順番にスクリプトを評価することができます:

var scripts = ['script1.js','script2.js','script3.js'], 

    //setup object to store results of AJAX requests 
    responses = {}; 

//create function that evaluates each response in order 
function eval_scripts() { 
    for (var i = 0, len = scripts.length; i < len; i++) { 
     eval(responses[scripts[i]]); 
    } 
} 

$.each(scripts, function (index, value) { 
    $.ajax({ 
     url  : scripts[index], 

     //force the dataType to be `text` rather than `script` 
     dataType : 'text', 
     success : function (textScript) { 

      //add the response to the `responses` object 
      responses[value] = textScript; 

      //check if the `responses` object has the same length as the `scripts` array, 
      //if so then evaluate the scripts 
      if (responses.length === scripts.length) { eval_scripts(); } 
     }, 
     error : function (jqXHR, textStatus, errorThrown) { /*don't forget to handle errors*/ } 
    }); 
}); 
+0

Ahh、ninja'd。しかし、うまくいく。 –

+0

これは動作しているようです!、あなたと非常に良いexplainationありがとう! – greenbandit

0

あなたは()配列ソートすることができます -

var sorted = scripts.sort(); 

してから、各機能でソートを使用します。

+0

OPの質問はAJAXリクエストの回答の順番に関するものです。 – Jasper

1

一部のスクリプトはサイズが異なる可能性があるため、予測できません。このようなことを試してみてください。

var scripts = ['script1.js','script2.js','script3.js'], ScriptIndex = 0; 
function LoadScript(index){ 
    if(index >= scripts.length) 
     return; 

    $.getScript(scripts[index], function(){ 
     console.log('Loaded script '+ scripts[index]); 
     LoadScript(++ScriptIndex); 
    } 
} 

これは、最後のスクリプトが完全に読み込まれた後に各スクリプトを読み込む必要があります。あなたはあなたがjqXhr object$.getScript(および他のすべてのAjax方法)によって返された事実を利用して作るLoadScript(0);

+0

'++ ScriptIndex'と' ScriptIndex ++ '(もしあれば)の違いは何ですか? – Jasper

+0

'++ ScriptIndex'が設定され、ANDがインクリメントされた値を返しますが、' ScriptIndex ++ 'はインクリメントされた値を設定します。 –

+1

gotcha、ありがとう。 – Jasper

10

関数を呼び出すことによって、それを起動していることを確認してください約束インタフェースを実装し、したがって、チェーン繰延オブジェクトに使用することができます.pipe()を提供:詳細については

var deferred = new $.Deferred(), 
    pipe = deferred; 

$.each(scripts , function(i, val) { 
    pipe = pipe.pipe(function() { 
     return $.getScript(val, function() { 
      console.log('loaded '+ val); 
     }); 
    }); 
}); 

deferred.resolve(); 

は、deferred objectsdeferred.pipeを見てみましょう。

全体として、遅延オブジェクトを使用すると柔軟性が向上し、エラーハンドラを簡単に追加できるようになります。

+0

私は繰延について学んだので、私はそれらを愛する。しかし、何とか私はパイプの特徴を見逃していました。素晴らしい投稿! – roberkules

+0

これは役に立ちません - あなたは基本的に '$ .when($ .getScript(a)、$ .getScript(b))'を実行しています - 'scripts'はサーバからロードされた直後もevalされています。以前のものが既にダウンロードされているかどうかにかかわらず。 – Dwelle

+0

@Dwellee:いいえ、そうではありません。 '$ .getScript(b)'は '$ .getScript(a)'がダウンロードされた後にのみ呼び出される '.pipe'コールバックの中で呼び出されます(評価されたかどうかはわかりません)。 –

2

ジャスパーのソリューション@の強化バージョン:呼び出しを同期する$.whenを使用して

  • グローバル evalを使用します。ここで

コードです:

/** 
* Load scripts in parallel keeping execution order. 
* @param {array} An array of script urls. They will parsed in the order of the array. 
* @returns {$.Deferred} 
*/ 
function getScripts(scripts) { 
    var xhrs = scripts.map(function(url) { 
     return $.ajax({ 
      url: url, 
      dataType: 'text', 
      cache: true 
     }); 
    }); 

    return $.when.apply($, xhrs).done(function() { 
     Array.prototype.forEach.call(arguments, function(res) { 
      eval.call(this, res[0]); 
     }); 
    }); 
} 

この要旨:https://gist.github.com/ngryman/7309432