使用jQuery.getScript 目前无法*使用“第一种方式”,因为它只支持异步操作,因此在被调用后会立即返回。
当脚本尝试调用myHelperFunction() 时,由于它在您的脚本下载之前返回,因此myHelperFunction 是undefined 并导致该错误。
*请参阅此答案底部的更新,了解一种有前途的新方法,最终将允许您编写几乎像您想要的样式一样工作的代码。 p>
您可以使用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 一样使用回调,所以你不能使用你想坚持的顺序样式。这是一个很好的折衷方案,因为连续执行多个同步 jQuery.ajax 调用只会加剧该方法的问题。
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 对象,或者其他承诺的实现,如从 AJAX 调用返回的 jQuery 就足够了。如果需要 ES6 Promise,则需要使用返回 Promise 的函数包装 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。