2012-03-14 3 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 sorted = scripts.sort(); 

및 -) (

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

아, 닌자. 그래도 좋은 일. –

+0

이것이 작동하는 것 같습니다!, 감사합니다. 아주 좋은 설명입니다! – greenbandit

0

당신은 정렬 할 수 있습니다 배열 : 시간 당신은 순서대로 스크립트를 평가할 수 있습니다.

+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); 
    } 
} 

마지막 스크립트가 완전히로드 된 후 각 스크립트를로드해야합니다. 있는지 확인은 LoadScript(0);

+0

'++ ScriptIndex'와'ScriptIndex ++'(있는 경우)의 차이점은 무엇입니까? – Jasper

+0

'++ ScriptIndex'는 설정하고, 증가 된 값을 반환합니다. 반면에'ScriptIndex ++'는 단지 증가 된 값을 설정합니다. –

+1

gotcha, 감사합니다. – Jasper

10

당신은 사실을 활용할 수 있도록 기능을 호출하여을 시작 jqXhr object$.getScript (그리고 다른 모든 아약스 방법)에 의해 반환되는 약속 인터페이스를 구현하기 때문에 체인 연기 객체에 사용할 수있는 .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 여기

코드이다.