异步函数调用是否有可能在两个同步语句之间完成?
Is it possible for an asynchronous function call to finish between two synchronous statements?
我正在编写一个脚本,该脚本将使用 AJAX 调用(当然是异步的,默认情况下是异步的)按需从服务器获取指定资源 r
,然后使用服务器返回的资源调用回调函数f
。
为了提高效率,如果给定的资源已经被请求,我希望脚本不要启动另一个 AJAX 调用,而是在已经加载的资源完成下载时执行回调:
JavaScript
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();
}
};
AJAX 调用在 nowLoading.hasOwnProperty(r)
[=36= 之间完成的可能性 微不足道 ]and nowLoading[r].OnReady = fn
语句?
还是我对JS的这方面理解有误,OnReady
只能在顺序语句执行完后才会发生?
前者意味着附加到 nowLoading
的 属性 的回调可能永远不会执行,因为 OnReady
发生在附加任何东西之前。
注意:OnReady
是 XHR.onreadystatechange
的特殊自定义案例。另请注意,为了简单起见,OnReady
不会清除以前的处理程序,而是添加一个新的处理程序。
Javascript 使用单线程执行(有一些引擎尝试使用多线程,但它们负责让事情看起来像是在单线程上发生的。)
现在,回答你的问题。由于您正在 运行 一些代码,并且没有双线程(调用完成后,它将在主线程上将回调注册为 运行)。
所以,不,代码不可能 运行 在语句之间,因为它 运行 在同一个线程上,并且只会 运行 当前执行一次堆栈已完全展开。
这是 Javascript 事件循环的顶部 Google 结果,它应该概述背景中发生的事情,以使所有这些协同工作。
http://2014.jsconf.eu/speakers/philip-roberts-what-the-heck-is-the-event-loop-anyway.html
关于你问题的第二部分:
The former would mean that it is possible for the callback attached to
a property of nowLoading to never get executed, since OnReady occurred
before attaching anything to it.
Javascript 的模型确实意味着如果调用同步完成,这可能会发生。然而,在这种情况下,由于您使用的是 Ajax,调用将永远不会同步执行,因此回调将始终被注册。
不,这不可能。这是 JS 的一个特性:
Each message is processed completely before any other message is
processed. This offers some nice properties when reasoning about your
program, including the fact that whenever a function runs, it cannot
be pre-empted and will run entirely before any other code runs (and
can modify data the function manipulates). This differs from C, for
instance, where if a function runs in a thread, it can be stopped at
any point to run some other code in another thread.
因此,一旦您开始 运行 一些同步代码,异步代码将等待同步代码完成。
异步函数就是:异步。但是,由于 JS 是单线程的(除非你使用的是真正多线程的 HTML5's Web Workers,但这里不是这种情况),这意味着事件回调函数不会执行,直到运行时引擎空闲.
所以,答案是否定的。代码中的回调不能在 2 个同步语句之间执行。
我正在编写一个脚本,该脚本将使用 AJAX 调用(当然是异步的,默认情况下是异步的)按需从服务器获取指定资源 r
,然后使用服务器返回的资源调用回调函数f
。
为了提高效率,如果给定的资源已经被请求,我希望脚本不要启动另一个 AJAX 调用,而是在已经加载的资源完成下载时执行回调:
JavaScript
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();
}
};
AJAX 调用在 nowLoading.hasOwnProperty(r)
[=36= 之间完成的可能性 微不足道 ]and nowLoading[r].OnReady = fn
语句?
还是我对JS的这方面理解有误,OnReady
只能在顺序语句执行完后才会发生?
前者意味着附加到 nowLoading
的 属性 的回调可能永远不会执行,因为 OnReady
发生在附加任何东西之前。
注意:OnReady
是 XHR.onreadystatechange
的特殊自定义案例。另请注意,为了简单起见,OnReady
不会清除以前的处理程序,而是添加一个新的处理程序。
Javascript 使用单线程执行(有一些引擎尝试使用多线程,但它们负责让事情看起来像是在单线程上发生的。)
现在,回答你的问题。由于您正在 运行 一些代码,并且没有双线程(调用完成后,它将在主线程上将回调注册为 运行)。
所以,不,代码不可能 运行 在语句之间,因为它 运行 在同一个线程上,并且只会 运行 当前执行一次堆栈已完全展开。
这是 Javascript 事件循环的顶部 Google 结果,它应该概述背景中发生的事情,以使所有这些协同工作。
http://2014.jsconf.eu/speakers/philip-roberts-what-the-heck-is-the-event-loop-anyway.html
关于你问题的第二部分:
The former would mean that it is possible for the callback attached to a property of nowLoading to never get executed, since OnReady occurred before attaching anything to it.
Javascript 的模型确实意味着如果调用同步完成,这可能会发生。然而,在这种情况下,由于您使用的是 Ajax,调用将永远不会同步执行,因此回调将始终被注册。
不,这不可能。这是 JS 的一个特性:
Each message is processed completely before any other message is processed. This offers some nice properties when reasoning about your program, including the fact that whenever a function runs, it cannot be pre-empted and will run entirely before any other code runs (and can modify data the function manipulates). This differs from C, for instance, where if a function runs in a thread, it can be stopped at any point to run some other code in another thread.
因此,一旦您开始 运行 一些同步代码,异步代码将等待同步代码完成。
异步函数就是:异步。但是,由于 JS 是单线程的(除非你使用的是真正多线程的 HTML5's Web Workers,但这里不是这种情况),这意味着事件回调函数不会执行,直到运行时引擎空闲.
所以,答案是否定的。代码中的回调不能在 2 个同步语句之间执行。