我可以在没有回调的情况下使用jquery getScript()吗?
我需要在另一个js文件中使用外部js文件中的javascript函数。 这基本上是我尝试过的代码:
$.getScript('js/myHelperFile.js'); myHelperFunction();
这不起作用 – 我收到“myHelperFunction未定义”的错误。
但是,此代码有效:
$.getScript('js/myHelperFile.js', function(){myHelperFunction();});
我特别希望能够以第一种方式完成它 – 将文件加载到我的文件顶部,然后使用我需要的任何函数。 这是可能的,还是我误解了getScript的工作原理?
使用jQuery.getScript
目前无法实现“第一种方式”,因为它只支持异步操作,因此在调用后立即返回。
由于在脚本尝试调用myHelperFunction()
时下载脚本之前返回,因此myHelperFunction
undefined
并导致该错误。
* 请参阅本答案底部的更新,了解一种有前途的新方法,该方法最终将允许您编写几乎与您所需风格类似的代码。
您可以使用jQuery.ajax
并将async
设置设置为false
,其代码如下所示:
$.ajax({ url: 'js/myHelperFile.js', async: false, dataType: "script", }); myHelperFunction();
但正如文件所述:
同步请求可能会暂时锁定浏览器,在请求处于活动状态时禁用任何操作。
这是一件非常糟糕的事情 。 如果提供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-08
jQuery 1.5发布 ,提供了另一种纯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-03-30
我最近阅读了一篇文章 ,让我了解了一个新的JavaScriptfunction,该function将来可能会启用您想要使用的那种程序外观的异步代码! 异步函数将使用await
关键字暂停执行async
函数,直到异步操作完成。 坏消息是它目前被列入ES7,两个ECMAScript版本。
await
依赖于等待返回Promise的异步函数。 我不确定浏览器实现将如何表现,如果它们需要一个真正的ES6 Promise对象,或者如果其他实现的promise(如jQuery从AJAX调用返回)就足够了。 如果需要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将代码转换为将在当前浏览器中运行的代码。 这样做的另一个好处是,您也可以使用许多其他有用的新ES6function 。
getScript()
使用getScript()
函数,我认为你不能。 问题是脚本是使用AJAX加载的(事实上, getScript
只是一个特殊的$.ajax()
函数的简写),当浏览器尝试在下一行执行函数时,也许服务器还没有退回了文件。
如果您不希望使用回调函数,则需要以原始forms使用jQuery $.ajax()
函数(并忘记getScript()
),并将传输设置为同步 。 这样,您可以确保在继续执行代码之前加载脚本:
$.ajax({ url: url, dataType: "script", async: false });
$ .getScript,默认情况下,所有与HTTP OP相关的jQuery函数都是非阻塞调用。 也就是说,操作完成时代码不会挂起。 这意味着上面的代码肯定会失败,因为$ .getScript无法在尝试执行该方法的行运行之前加载脚本。 这就是回调函数被接受为参数的原因。
但是,您正在尝试做的事情是可能的。 加载脚本后,您应该可以从任何地方调用它。 避免在下载脚本之前调用该方法所需的一切是设置必要的标志。
var HelperFileLoaded = false; $.getScript('js/myHelperFile.js', function() { HelperFileLoaded = true; }); // ... function btnSaveClick() { if(!HelperFileLoaded) return; myHelperFunction(); }
BenM的建议是可能的,但除非您只调用myHelperFunction,否则它将无法作为解决方案,因为在触发调用myHelperFunction的任何其他方法之前无法保证脚本已经下载。
如果你使用JSONP,你的第一个工作正常,我经常这样做。