您似乎对 JS 的工作原理感到困惑:
函数进行 AJAX 调用,并且在返回 AJAX 结果之前不应返回。麻烦的是,AJAX 函数运行在一个单独的异步线程中
这句话包含几个谬误:
- 函数进行 AJAX 调用,并且在返回 AJAX 结果之前不应返回
- AJAX 函数在单独的异步线程中运行
这两种说法都完全不真实,原因如下:
进行 ajax 调用的函数就是这样做的:它发出一个调用,它发送一个请求。 AJAX 代表 Asynchronous JavaScript And XML,这是一个发出此类请求的函数,然后在请求发送后返回。请求会发生什么,以及在发回响应后如何处理它不是发出请求的函数的责任。考虑一下:
function sendInfo(info)
{
var loader = $('#loader');
$.ajax({
url: 'your/url',
data: info,
type: 'post',
success: function(response)
{//this will get called when there is a response
loader.hide();//access to outer scope!
}
});
loader.show();
}
在这种情况下,$.ajax 是执行请求的函数。如果那是阻塞的,我们将无法显示加载程序。但是,该函数会在发送请求后返回,一旦有要处理的响应,就会调用success 回调。该函数将负责加载程序,即再次隐藏它。如果 AJAX 调用被阻止,我们就不会像今天几乎所有网站那样拥有响应式和动态的网站(自动完成谷歌搜索,甚至这个网站......)
AJAX 函数在单独的线程中运行是不正确的。 AJAX 是一种请求,您所指的函数是发出请求的函数,它们不在单独的线程中运行,或者是回调/句柄。这些也不在单独的线程中运行。
JavaScript 一直是单线程的。它确实有一个事件循环。在每个事件上,JS 检查是否有绑定到处理该事件的侦听器。如果没有,那就结束,如果有,这些处理程序将一次调用一个。在调用这些处理程序时,不能执行其他代码。
现在回答您的问题:我们如何从这些函数返回?好吧,在某种程度上,你已经是:所有函数都返回一些东西。但是我认为您想知道如何将这些函数的返回值分配给变量。简单的答案是:你不能。至少不是直接的:
//not using jQuery:
var returnVal = xhr.send();
不会返回成功 (onreadystatechange) 处理程序的值,因为onreadystatechange 事件将发生 4 次!您可以做的是使用闭包变量、模块模式,或者,如果必须的话,使用全局变量。
如果这些函数在单独的线程中运行,作用域和访问全局变量会给你留下很多并发问题,并且操作 DOM 将是正确的。相反,您可以这样做:
var infoModule = (function()
{
var loader = $('#loader'),
module = {response: undefined};
module.sendInfo = function(info)
{
$.ajax({
url: 'your/url',
data: info,
type: 'post',
success: function(response)
{//this will get called when there is a response
loader.hide();//access to outer scope!
module.response = response;
}
});
loader.show();
};
return module;
}());
现在你可以这样做了:
infoModule.sendInfo({data: 'foo'});
请求完成后,您可以像这样得到调用的响应:
infoModule.response;