這樣做「第一種方式」目前不是*可能與jQuery.getScript
,因爲它只支持異步操作,因此它被調用後立即返回。
由於在腳本嘗試調用myHelperFunction()
,myHelperFunction
時出現腳本下載之前,它會返回undefined
並導致該錯誤。
*看到這個答案的底部有前途的新方法,最終將讓你編寫代碼,幾乎就像你所需的樣式更新。
你可以使用jQuery.ajax
與async
設置設爲false
與代碼是這樣做的:
$.ajax({
url: 'js/myHelperFile.js',
async: false,
dataType: "script",
});
myHelperFunction();
但爲documentation狀態:
同步請求可能暫時鎖定瀏覽器,在請求處於活動狀態時禁用任何操作。
這是一件非常糟糕的事情。如果提供myHelperFile.js
的服務器在任何時間響應都很慢(某些時候將發生),則該頁面將變爲無響應狀態,直到請求結束或超時。
接受在整個jQuery中大量使用的回調風格將是一個更好的主意。
$.getScript('js/myHelperFile.js', function() {
myHelperFunction();
});
你並不需要或者可以使用匿名函數,你可以把你的代碼在名爲功能:
function doStuffWithHelper() {
myHelperFunction();
}
$.getScript('js/myHelperFile.js', doStuffWithHelper);
如果您需要在調用之前加載多個依賴myHelperFunction
除非您在執行代碼之前設置了某種系統來確定是否下載了所有依賴項,否則這將不起作用。然後,您可以在所有.getScript
調用中設置回調處理程序,以檢查是否在運行代碼之前加載了所有依賴項。
var loadedScripts = {
myHelperFile: false,
anotherHelperFile: false
};
function doStuffWithHelper() {
// check to see if all our scripts are loaded
var prop;
for (prop in loadedScripts) {
if (loadedScripts.hasOwnProperty(prop)) {
if (loadedScripts[prop] === false) {
return; // not everything is loaded wait more
}
}
}
myHelperFunction();
}
$.getScript('js/myHelperFile.js', function() {
loadedScripts.myHelperFile = true;
doStuffWithHelper();
});
$.getScript('js/anotherHelperFile.js', function() {
loadedScripts.anotherHelperFile = true;
doStuffWithHelper();
});
正如您所看到的,這種方法變得複雜且難以維護。
如果您確實需要加載多個依賴關係,您最好使用諸如yepnope.js這樣的腳本加載器來執行此操作。
yepnope({
load : [ 'js/myHelperFile.js', 'js/anotherHelperFile.js' ],
complete: function() {
var foo;
foo = myHelperFunction();
foo = anotherHelperFunction(foo);
// do something with foo
}
});
Yepnope使用回調只是想.getScript
,所以你不能用你想堅持使用順序的風格。這是一個很好的折衷,但因爲在同一行中執行多個同步調用只會複合該方法的問題。
更新2013年12月8日
的jQuery 1.5 release,提供了這樣做的另一個純jQuery的方式。作爲1.5,所有的AJAX請求返回Deferred Object,所以你可以這樣做:
$.getScript('js/myHelperFile.js').done(function() {
myHelperFunction();
});
作爲一個異步請求,這當然需要一個回調。然而,使用Deferreds擁有傳統的回調製度的巨大優勢,使用$.when()你可以很容易地擴展爲加載多個先決條件腳本,而無需自己錯綜複雜的跟蹤系統:
$.when($.getScript('js/myHelperFile.js'), $.getScript('js/anotherHelperFile.js')).done(function() {
var foo;
foo = myHelperFunction();
foo = anotherHelperFunction(foo);
// do something with foo
});
這將同時下載腳本和只執行回調之後他們都被下載了,就像上面的Yepnope示例一樣。
更新2014年3月30日
最近,我讀an article讓我意識到一個新的JavaScript功能,可能在未來實現那種程序,尋找至今沒有異步代碼的那你想用! Async Functions將使用await
關鍵字來暫停執行async
函數,直到異步操作完成。壞消息是,它目前將被納入ES7,兩個ECMAScript版本。
await
依賴於您正在等待的異步函數返回Promise。我不確定瀏覽器實現的行爲方式,如果它們需要一個真正的ES6 Promise對象,或者其他實現的承諾(如jQuery從AJAX調用返回)就足夠了。如果需要ES6承諾,你將需要包裝jQuery.getScript
與返回無極功能:
"use strict";
var getScript = function (url) {
return new Promise(function(resolve, reject) {
jQuery.getScript(url).done(function (script) {
resolve(script);
});
});
};
然後你可以用它來下載和await
,然後再繼續:
(async function() {
await getScript('js/myHelperFile.js');
myHelperFunction();
}());
如果你是真的決定今天寫這種風格,你可以使用asyc
和await
,然後用Traceur將代碼轉換成可以在當前瀏覽器中運行的代碼。這樣做的附加好處是你也可以使用很多other useful new ES6 features。
令人驚訝的全面的答案,做得好! – GregL
+!相當完整的答案。 Howerever,如果你爲jQuery加載時爲什麼要迭代for..in'合成器? –
@ gion_13它允許我從內部返回if(loadedScripts [prop] === false){'退出該函數,以便下列依賴於依賴關係的代碼不會運行。如果我使用'$ .each',我可以用'return false'儘早停止循環,但是循環後面的代碼會運行,我必須在循環之前設置某種標誌,然後在循環之後檢查它以防止代碼運行。使用'for..in'循環並退出函數更清晰。現在看看它,而不是字典,我會只使用一個計數變量,並將其與全部腳本進行比較。 –