是否有可能在两个同步语句之间完成异步函数调用?

时间:2015-03-02 15:29:16

标签: javascript ajax asynchronous

我正在编写一个脚本,可以根据需要使用AJAX调用从服务器获取指定的资源r(当然,默认情况下是异步),然后调用回调函数{{ 1}}与服务器返回的资源。

为了提高效率,如果已经请求了给定资源,我希望脚本不启动另一个AJAX调用,而是在已经加载资源完成下载时执行回调:

的JavaScript

f

var nowLoading = {}; /** * @param {String} r - The resource identifier * @param {Object} f - Callback function with returned resource */ function Load(r, f) { if (nowLoading.hasOwnProperty(r)) { // the given resource is already being requested, listen to it being finished nowLoading[r].OnReady = function () { // ... f(resource); }; } else { // make a new request var xhr = XHRFactory.Spawn(); nowLoading[r] = xhr; xhr.OnReady = function () { // ... f(resource); }; xhr.open('GET', url); xhr.send(); } }; nowLoading.hasOwnProperty(r) 之间,是否存在边缘可能性语句吗

或者我在这方面误解了JS,nowLoading[r].OnReady = fn只能在顺序语句执行完毕后才会发生?

前者意味着附加到OnReady属性的回调可能永远不会被执行,因为nowLoading在附加任何内容之前就已经发生了。


注意:OnReadyOnReady的特殊自定义案例。另请注意,为简单起见,XHR.onreadystatechange不会清除先前的处理程序,而是添加一个新的处理程序。

3 个答案:

答案 0 :(得分:1)

Javascript使用单个线程执行(有一些引擎可以尝试多线程,但是它们会让事情看起来像是在一个线程上发生的。)

现在,针对您的问题。因为你正在运行一些代码,并且没有双线程(当调用完成时,它将注册回调以在主线程上运行。)

所以,不,代码不可能在语句之间运行,因为它运行在同一个线程上,并且只有在当前执行堆栈完全展开后才会运行。

以下是Javascript事件循环的Google最佳结果,该结果应概述后台发生的事情,以便将所有这些工作结合在一起。

http://2014.jsconf.eu/speakers/philip-roberts-what-the-heck-is-the-event-loop-anyway.html

至于问题的第二部分:

  

前者意味着可以附加回调   由于OnReady发生,nowLoading的属性永远不会被执行   在附上任何东西之前。

Javascript的模型确实意味着如果调用同步完成,可能会发生这种情况。但是,在这种情况下,由于您使用的是Ajax,因此永远不会同步执行调用,因此将始终注册回调。

答案 1 :(得分:1)

不,这是不可能的。这是JS的一个特色:

  

"Run-to-completion"

     

在完成任何其他消息之前,将完全处理每条消息   处理。这在推理你的时候提供了一些不错的属性   程序,包括每当一个函数运行的事实,它不能   被抢占,将在任何其他代码运行之前完全运行(和   可以修改函数操作的数据)。这与C不同   例如,如果函数在一个线程中运行,则可以在其中停止   任何在另一个线程中运行其他代码的点。

因此,一旦开始运行某些同步代码,异步代码将等待同步代码完成。

答案 2 :(得分:1)

异步函数就是:Asyncronous。但是,由于JS是单线程的(除非你使用的是HTML5's Web Workers,这是真正的多线程,但在这里并非如此),这意味着事件回调函数在运行时引擎之前不会执行免费。

所以,答案是否定的。代码中的回调不能在两个同步语句之间执行。