我可以使用没有回调的jquery getScript()吗? [英] Can I use jquery getScript() without a callback?

查看:97
本文介绍了我可以使用没有回调的jquery getScript()吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

$.getScript('js/myHelperFile.js');
myHelperFunction();

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

但是,此代码有效:

$.getScript('js/myHelperFile.js', function(){myHelperFunction();});

我特别希望能够以第一种方式进行操作-将文件加载到文件的顶部,然后从那里使用我需要的任何功能.这可能吗,还是我误解了getScript的工作原理?

解决方案

* 第一方式"进行. com/jQuery.getScript/"rel =" noreferrer> jQuery.getScript ,因为它仅支持异步操作,因此在被调用后立即返回.

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

* 请参阅此答案底部的更新,以获取有希望的新方法,该方法最终将使您能够编写几乎可以按所需样式工作的代码.

您可以使用 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请求都返回延迟对象,因此您可以执行以下操作:

$.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

我最近阅读了一篇文章,这使我意识到了JavaScript的一项新功能将来可能会启用您想要使用的那种看起来像过程的异步代码! 异步函数将使用await关键字暂停async函数的执行,直到异步操作完成.坏消息是,它目前预定包含在ES7中,而EC7则有两个版本.

await依赖于您等待返回承诺.我不确定浏览器的实现将如何运行,是否需要一个真正的ES6 Promise对象,或者其他的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();
}());

如果您今天真的确定要使用这种样式,则可以使用asycawait,然后使用其他有用的ES6新功能.

I need to use a javascript function from an external js file inside another js file. This is basically the code I've tried:

$.getScript('js/myHelperFile.js');
myHelperFunction();

This doesn't work - I get an error of "myHelperFunction is not defined".

However, this code works:

$.getScript('js/myHelperFile.js', function(){myHelperFunction();});

I specifically want to be able to do it the first way - load the file at the top of my file, and then use any functions I need from there on. Is this possible, or am I misunderstanding how getScript works?

解决方案

Doing it "the first way" is not presently* possible with jQuery.getScript because it only supports asynchronous operations, and thus it returns immediately after being called.

Since it returns before your script has been downloaded when the script tries to invoke myHelperFunction(), myHelperFunction is undefined and causes that error.

*See the update at the bottom of this answer for a promising new method that will eventually allow you to write code that almost works like your desired style.

You could do it using jQuery.ajax with the async setting set to false with code that is something like this:

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

myHelperFunction();

But as the documentation states:

synchronous requests may temporarily lock the browser, disabling any actions while the request is active.

This is a very bad thing. If the server that is providing myHelperFile.js is slow to respond at any time (which will happen at some point) the page will become unresponsive until the request finishes or timesout.

It would be a much better idea to embrace the callback style which is used heavily throughout jQuery.

$.getScript('js/myHelperFile.js', function () {
   myHelperFunction();
});

You don't need to use an anonymous function either, you can put your code in a named function:

function doStuffWithHelper() {
   myHelperFunction();
}

$.getScript('js/myHelperFile.js', doStuffWithHelper);


If you need to load more than one dependency before calling myHelperFunction this won't work unless you set up some sort of system to figure out if all of your dependencies are downloaded before you execute your code. You could then set the callback handler on all of the .getScript calls to check that all of your dependencies are loaded before running your code.

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();
});

As you can see, this kind of approach gets convoluted and unmaintainable fast.

If you do need to load multiple dependencies you would probably be better off using a scriptloader such as yepnope.js to do it.

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

Yepnope uses callbacks just like .getScript so you can not use the sequential style you wanted to stick with. This is a good tradeoff though because doing multiple synchronous jQuery.ajax calls in a row would just compound that methods problems.


Update 2013-12-08

The jQuery 1.5 release, provides another pure jQuery way of doing it. As of 1.5, all AJAX requests return a Deferred Object so you could do this:

$.getScript('js/myHelperFile.js').done(function () {
   myHelperFunction();
});

Being a asynchronous request, it of course requires a callback. Using Deferreds however has a huge advantage over the traditional callback system, using $.when() you could easily expand this to loading multiple prerequisite scripts without your own convoluted tracking system:

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

This would download both scripts simultaneously and only execute the callback after both of them were downloaded, much like the Yepnope example above.


Update 2014-03-30

I recently read an article that made me aware of a new JavaScript feature that may in the future enable the kind of procedural-looking-yet-async code that you wanted to use! Async Functions will use the await keyword to pause the execution of a async function until the asynchronous operation completes. The bad news is that it is currently slated for inclusion in ES7, two ECMAScript versions away.

await relies on the asynchronous function you are waiting on returning a Promise. I'm not sure how the browser implementations will behave, if they will require a true ES6 Promise object or if other implementations of promises like the one jQuery returns from AJAX calls will suffice. If a ES6 Promise is required, you will need to wrap jQuery.getScript with a function that returns a Promise:

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

Then you can use it to download and await before proceeding:

(async function () {
  await getScript('js/myHelperFile.js');
  myHelperFunction();
}());

If you are really determined to write in this style today you can use asyc and await and then use Traceur to transpile your code into code that will run in current browsers. The added benefit of doing this is that you could also use many other useful new ES6 features too.

这篇关于我可以使用没有回调的jquery getScript()吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆