我有一个foo
发出Ajax请求的函数。我如何从中返回响应foo
?
我尝试从success
回调中返回值,以及将响应分配给函数内部的局部变量并返回该局部变量,但这些方法均未真正返回响应。
function foo() {
var result;
$.ajax({
url: '...',
success: function(response) {
result = response;
// return response; // <- I tried that one as well
}
});
return result;
}
var result = foo(); // It always ends up being `undefined`.
除了了解代码之外,还有2个概念是理解JS如何处理回调和异步性的关键。(哪怕一个字?)
事件循环和并发模型
您需要注意三件事:队列; 事件循环和堆栈
从广义上来说,事件循环就像项目管理器一样,它一直在侦听任何想要运行的功能,并在队列和堆栈之间进行通信。
一旦收到运行某条消息的消息,就会将其添加到队列中。队列是等待执行的事物的列表(例如您的AJAX请求)。像这样想象:
当这些消息之一要执行时,它会从队列中弹出消息并创建一个堆栈,而该堆栈就是JS执行该消息中的指令所需的一切。因此,在我们的示例中,它被告知致电
foobarFunc
因此,foobarFunc需要执行的任何操作(在我们的示例中
anotherFunction
)将被压入堆栈。执行,然后被遗忘-事件循环将移至队列中的下一件事(或侦听消息)这里的关键是执行顺序。那是
什么时候会运行
当您使用AJAX呼叫外部方或运行任何异步代码(例如setTimeout)时,Javascript依赖于响应才能继续。
最大的问题是,它将何时获得响应?答案是我们不知道-事件循环正在等待该消息说“嘿,我快跑”。如果JS只是同步地等待该消息,则您的应用程序将冻结,并且将变得很糟糕。因此,JS在等待消息添加回队列的同时继续执行队列中的下一项。
这就是为什么在异步功能中我们使用了称为callbacks的东西。从字面上看,这有点像一个承诺。就像我保证在某个时候返回某些内容一样, jQuery使用称为
deffered.done
deffered.fail
和的特定回调deffered.always
。你可以在这里看到他们因此,您需要做的是传递一个函数,该函数应在传递给它的数据的某个点执行。
因为回调不是立即执行,而是在以后执行,所以将引用传递给未执行的函数很重要。所以
因此,大多数情况下(但并非总是如此),您
foo
不会foo()
希望这会有所道理。当您遇到这样令人困惑的事情时,我强烈建议您完整阅读文档以至少了解它。这将使您成为更好的开发人员。