这样做“第一种方式”目前不是*可能与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'循环并退出函数更清晰。现在看看它,而不是字典,我会只使用一个计数变量,并将其与全部脚本进行比较。 –