我可以在没有回调的情况下使用jquery getScript()吗?

fro*_*die 11 jquery getscript

我需要在另一个js文件中使用外部js文件中的javascript函数.这基本上是我尝试过的代码:

$.getScript('js/myHelperFile.js');
myHelperFunction();
Run Code Online (Sandbox Code Playgroud)

这不起作用 - 我收到"myHelperFunction未定义"的错误.

但是,此代码有效:

$.getScript('js/myHelperFile.js', function(){myHelperFunction();});
Run Code Online (Sandbox Code Playgroud)

我特别希望能够以第一种方式完成它 - 将文件加载到我的文件顶部,然后使用我需要的任何函数.这是可能的,还是我误解了getScript的工作原理?

Use*_*ode 30

这样做的"第一路"目前还不能*可能的jQuery.getScript,因为它只支持异步操作,因此它被称为后立即返回.

由于它在脚本尝试调用之前下载脚本之前返回myHelperFunction(),myHelperFunction因此undefined会导致该错误.

*请参阅本答案底部的更新,了解一种有前途的新方法,该方法最终将允许您编写几乎与您所需风格类似的代码.

你可以用它做jQuery.ajaxasync设置设置false的代码是这样的:

$.ajax({
  url: 'js/myHelperFile.js',
  async: false,
  dataType: "script",
});

myHelperFunction();
Run Code Online (Sandbox Code Playgroud)

正如文件所述:

同步请求可能会暂时锁定浏览器,在请求处于活动状态时禁用任何操作.

这是一件非常糟糕的事情.如果提供的服务器myHelperFile.js在任何时候响应缓慢(这在某个时间点发生),则在请求完成或超时之前,页面将无响应.

拥抱在jQuery中大量使用的回调样式会更好一点.

$.getScript('js/myHelperFile.js', function () {
   myHelperFunction();
});
Run Code Online (Sandbox Code Playgroud)

您也不需要使用匿名函数,可以将代码放在命名函数中:

function doStuffWithHelper() {
   myHelperFunction();
}

$.getScript('js/myHelperFile.js', doStuffWithHelper);
Run Code Online (Sandbox Code Playgroud)

如果您需要在调用之前加载多个依赖项,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();
});
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,这种方法很快就会变得复杂且难以维护.

如果你确实需要加载多个依赖项,那么使用像yepnope.js这样的脚本加载器可能会更好.

yepnope( {
        load : [ 'js/myHelperFile.js', 'js/anotherHelperFile.js' ],
        complete: function () {
            var foo;
            foo = myHelperFunction();
            foo = anotherHelperFunction(foo);
            // do something with foo
        }
} );
Run Code Online (Sandbox Code Playgroud)

Yepnope使用回调就像.getScript你不能使用你想要坚持的顺序样式.这是一个很好的权衡,因为jQuery.ajax连续执行多个同步调用只会使这些方法出现问题.


更新2013-12-08

jQuery的1.5版本,提供了这样做的另一个纯jQuery的方式.从1.5开始,所有AJAX请求都返回一个Deferred Object,因此你可以这样做:

$.getScript('js/myHelperFile.js').done(function () {
   myHelperFunction();
});
Run Code Online (Sandbox Code Playgroud)

作为异步请求,它当然需要回调.然而,使用Deferreds比传统的回调系统具有巨大的优势,使用$ .when()您可以轻松地将其扩展为加载多个必备脚本而无需您自己的复杂跟踪系统:

$.when($.getScript('js/myHelperFile.js'), $.getScript('js/anotherHelperFile.js')).done(function () {
  var foo;
  foo = myHelperFunction();
  foo = anotherHelperFunction(foo);
  // do something with foo
});
Run Code Online (Sandbox Code Playgroud)

这将同时下载两个脚本,并且只在下载两个脚本后执行回调,就像上面的Yepnope示例一样.


更新2014-03-30

我最近阅读了一篇文章,让我了解了一个新的JavaScript功能,该功能将来可能会启用您想要使用的那种程序外观的异步代码!异步函数将使用该await关键字暂停async函数的执行,直到异步操作完成.坏消息是它目前被列入ES7,两个ECMAScript版本.

await依赖于等待返回Promise的异步函数.我不确定浏览器实现将如何表现,如果它们需要一个真正的ES6 Promise对象,或者其他实现的promises如jQuery从AJAX调用返回就足够了.如果需要ES6 Promise,则需要jQuery.getScript使用返回Promise的函数进行换行:

"use strict";
var getScript = function (url) {
  return new Promise(function(resolve, reject) {
    jQuery.getScript(url).done(function (script) {
      resolve(script);
    });
  });
};
Run Code Online (Sandbox Code Playgroud)

然后你可以使用它来下载并await继续之前:

(async function () {
  await getScript('js/myHelperFile.js');
  myHelperFunction();
}());
Run Code Online (Sandbox Code Playgroud)

如果你真的有决心在今天这种风格来写,你可以使用asycawait再利用Traceur到transpile你的代码的代码,将在目前的浏览器上运行.这样做的另一个好处是,您也可以使用许多其他有用的新ES6功能.