2010-11-22 20 views
0

我有以下javascript列表,這個列表中的每個項目都有一個腳本文件url和一個回調函數,我想要做的就是迭代這個列表,加載每個腳本,然後執行回調函數,並移動到下一個項目,除非當前的回調執行完畢..使用連續回調自動加載JavaScript文件


var data = { 
    scripts: [ 
     { 
      file : 'some-script.js', 
      callback: function() { 
       // do some code here 
      }, 
     }, 
     { 
      file : 'another-script.js', 
      callback: function() { 
       // do some code here 
      }, 
     }, 
     ... 
    ] 
}; 

我怎麼能做到這一點自動,如果可能的話?

+1

**題外話**:在你的對象文本的最後一個屬性之後,那些晃來晃去逗號將是你的問題在一些瀏覽器,細節:http://blog.niftysnippets.org/2010 /09/literal-improvement.html – 2010-11-22 11:00:47

+0

我放置了這個逗號,表示將會有超過這些腳本被加載,無論如何感謝您的評論,也爲帖子,但我不認爲放置超時是一件好事的想法,因爲我打算做一些普遍適用的東西,不管它包含什麼回調代碼.. – 2010-11-22 14:32:25

回答

2

(我假設您使用JSONP來加載您的外部腳本)您將面臨的問題是,這些腳本不會同時加載所有腳本。

下面是一些代碼,一旦關聯的腳本被加載就會調用你的回調函數。

function include_js(url, callback) { // http://www.nczonline.net 
     var script = document.createElement("script"); 
     script.type = "text/javascript"; 

     if (script.readyState) { //IE 
      script.onreadystatechange = function(){ 
       if (script.readyState == "loaded" || script.readyState == "complete"){ 
        script.onreadystatechange = null; 
        callback(); 
       } 
      }; 
     } else { //Others 
      script.onload = function(){ 
       callback(); 
      }; 
     } 
     script.src = url; 
     document.getElementsByTagName("head")[0].appendChild(script); 
    } 

//Edit 

    for (var i = 0; i < data.scripts.length; i++) { 
     include_js(data.scripts[i].file, data.scripts[i].callback); 
    } 
+0

完美運作! – 2010-11-22 14:33:11

+0

我在這裏理解的是,在你的for循環中,直到匿名函數完成它的代碼執行,它纔會進入列表中的下一個元素? – 2010-11-22 14:58:24

1

這是可能的如果有一個符號可以在每個腳本中測試,或者每個腳本可以在完成加載時執行函數調用。

加載腳本很容易,因爲我敢肯定你知道(你會看到人們追加到head代替;沒有關係,和body是很容易找到)

var script = document.createElement('script'); 
script.src = /* ... the source path ... */; 
document.body.appendChild(script); 

但困難的部分是知道它何時被下載和執行。唯一真正的方法是通過輪詢來查看由腳本定義的新全局符號是否已經定義,或者在腳本完成加載時腳本會主動回覆(a'la JSONP)。

無論哪種方式,一旦您檢測到符號或獲得回調,然後您繼續加載下一個腳本。

這裏是做找到一個全球性的符號(在window對象上的屬性)的基礎上的快速和骯髒的草圖:

// The scripts to load 
var scriptList = { 
    scripts: [ 
     { 
      file : 'some-script.js', 
      callback: function() { 
       // do some code here 
      }, 
      symbol : "someSymbol", 
      timeout : 30000 // We know this one is slow, give it 30 seconds 
     }, 
     { 
      file : 'another-script.js', 
      callback: function() { 
       // do some code here 
      }, 
      symbol : "anotherSymbol" 
     }, 
     // ... 
    ] 
}; 

// Triggering the load 
loadScripts(scriptList); 

// Library routines to do the load 
function loadScripts(list) 
{ 
    var index, timeout; 

    // Start with the first one (loadNextScript starts with an increment) 
    index = -1; 
    loadNextScript(); 

    // This function loads the next script in the list; if there are no 
    // more, it simply returns 
    function loadNextScript() 
    { 
     var script; 

     // Are there more? 
     ++index; 
     if (index < list.length) 
     { 
      // Yes, append a `script` element 
      script = document.createElement('script'); 
      script.src = list.file; 
      document.body.appendChild(script); 

      // Determine when to time out 
      timeout = new Date() + (list[index].timeout || 20000); // Time out in Xms, default 20 seconds 

      // Start polling 
      setTimeout(pollForScript, 0); // Async, but almost immediately (4-10ms on most browsers) 
     } 
    } 

    // This function polls to see if the current script has loaded yet by 
    // checking for a global symbol it defines. 
    function pollForScript() 
    { 
     var result; 

     // Has it been too long? 
     if (new Date() > timeout) 
     { 
      // Yes 
      result = "timeout"; 
     } 
     else 
     { 
      // Has the symbol been defined? 
      if (typeof window[list[index].symbol] !== "undefined") 
      { 
       // Yes 
       result = "loaded"; 
      } 
      else 
      { 
       // Nope, keep waiting 
       setTimeout(pollForScript, 250); // Check every quarter-second 
      } 
     } 

     // Did we get a result? 
     if (result) 
     { 
      // Yes, do the callback telling it of the result 
      try { 
       list[index].callback(result); 
      } 
      catch (e) { 
      } 

      // Load the next script 
      loadNextScript(); 
     } 
    } 
} 
0

讓回調打電話給你loadTheNextScriptInList或任何功能。您可以通過向onLoad事件添加匿名函數來自動執行此操作。這個匿名函數應該首先調用列表中的回調集,然後調用你的loadTheNextScriptInList函數。

0

這只是我寫了和HAVENT TESTED的快速的東西,但它應該以遞歸的方式做你以後的事情。希望這會有所幫助:

var data = { 
    scripts: [ 
     { 
      file : 'some-script.js', 
      callback: function() { 
       // do some code here 
      }, 
     }, 
     { 
      file : 'another-script.js', 
      callback: function() { 
       // do some code here 
      }, 
     }, 
     ... 
    ] 
}; 


$(document).ready(function() { 

    if(data.scripts.length > 0) { 
     scriptLoader(0); 
    } 

}); 

function scriptLoader(i) { 


    var currScript = data.scripts[i]; 


    $.getScript(currScript.file, function() { 

     // execute your callback 
     currScript.callback(); 

     // load next script 
     if(i < data.scripts.length) { 
     scriptLoader(i++); 
     } 

    }); 

} 

哦,順便說一句,這使用JQuery JavaScript框架,只是FYI。

+0

只是想我會提到,這是沒有太大的用處,我嘗試動態加載jQuery和它的依賴文件順序。不過看起來很簡單。:P – purefusion 2011-08-01 19:50:18