为什么回调被认为是异步的,如果我们需要等待
我读过Why do I have to use await for a method to run asynchronously. What if I don't want to wait for the method to finish before continuing?和Are callbacks always asynchronous?,我仍然试图了解何时回调实际上是异步的。为什么回调被认为是异步的,如果我们需要等待
例如,doThat
在做任何事情之前都需要等待GET
数据。正如上面的第二个链接所述,javascript是单线程的。
doThis(doThat);
function doThis(callback) {
$.get('http://some_api/some_resource', function (data) {
callback(data);
});
};
function doThat(data) {
// Do something with data
};
只有我见过真正的异步功能与承诺,并承诺多在那里我可以,例如,当动画结束了加载其他数据。我希望能够帮助我们更好地理解传统回调是否实际上是异步的。具体的例子帮助。
例如,我可以在动画结束时加载其他数据。
这正是您可以对您的代码执行的操作。请注意,您可以在等待doThat
执行的同时运行其他代码(实际上“运行其他代码”会让人感到困惑)。酷似动画例如:
function doThis(callback) {
$.get('http://some_api/some_resource', function (data) {
callback(data);
});
};
function doThat(function (data) {
// Do something with data
});
function doAnotherThing(function (data) {
// Do something with data
});
doThis(doThat);
// without waiting for doThat to run, you can IMMEDIATELY call:
doThis(doAnotherThing);
// without waiting for either doThat or doAnotherThing you
// can output some pretty animations:
setInterval(do_animation,100);
// and without waiting for any of the above you can do anything else:
document.body.innerHTML += 'hello';
注意什么迷惑大多数人的是,document.body.innerHTML='hello'
部分运行之前任何它上面的代码。这意味着回调是异步的,因为当数据到达时执行,而不是在调用该函数时。
请注意,并非所有的回调都是异步的。例如,Array.prototype.forEach()
是同步的:
document.body.innerHTML += 'before<br>';
['hello','world'].forEach(function(x){
document.body.innerHTML += x;
})
document.body.innerHTML += '<br>after';
什么决定天气回调是异步或同步是调用它的函数。另请参阅:I know that callback function runs asynchronously, but why?
这是一个明确的解释。谢谢! – Growler
与定义开始:
不同步,在计算机编程,是指独立于主程序流程和方法来处理此类事件的事件的发生。这些可能是“外部”事件,例如信号的到来,或者是与程序执行同时发生的程序引发的行为,而不会阻止程序等待结果。
- Davies,Alex(2012)。在C#5.0中的异步,通过维基百科对Asynchrony (computer programming)
在JavaScript的情况下,它的工作原理是这样的(简化):有一个等待主线程(并且只有)执行的任务队列。加载脚本时,它是放置在该队列上的任务。一个任务运行直到它退出,并且其他任务都不会中断它。但是,任务可能导致其他任务被放置在队列中。当一个任务完成时,队列上的下一个任务开始。如果队列为空,则后来进入队列的第一个任务将立即执行。
的任务进入队列,除了是脚本的主要任务主要方式来解析和执行:触发事件将会把有关任务队列事件注册处理程序,并达到通过setTimeout
或setInterval
预定时间将关联的任务放置在任务队列中。
在JavaScript方面,该相同任务(“主程序流程”)内执行的一切被说成是同步。在未来任务中执行的所有内容都称为异步。另一种说法是 - 如果下一条语句在回调之前执行,则它是异步的;如果下一条语句在回调后执行,则它是同步的。
$.get(opts, callback)
是异步调用,因为执行功能callback
的任务将在onreadystatechange
事件触发时置于任务队列中。如果你有一个后面的声明,它会先执行;只有在任务完成后,由于AJAX调用更新而进入任务队列的任务才有机会运行。
相比之下,$.each(collection, callback)
是一个同步调用,因为callback
将从each
函数直接调用,而不必退出当前的任务,而不会自己反正产生任何额外任务(当然不是callback
可以产生额外的任务)。下一个陈述将不得不等到each
完成遍历collection
的每个元素。
请注意,承诺仅仅是对此机制的封装。所有你可以用承诺做的事情,你可以在没有它们的情况下做,只是代码不会很漂亮和清晰。
“回调”实际上只是一个函数,您将其作为参数传递给另一个函数,以便其他函数可以调用它,这个进程* *可以*都是同步的 - 它实际上取决于其他函数功能在做。但即使在像Ajax这样的异步情况下,它不是异步的回调函数本身,它最终会调用它是异步的。在你的例子中,'doThat()'不会等待 - 它是等待调用'doThat()'的其他代码(你的'doThat()'定义也是无效的)。 – nnnnnn
你可能想看看[所有的javascript回调是异步的吗?如果不是,我怎么知道哪些是?](http://stackoverflow.com/q/19083357/1048572)的一般问题和[什么是异步JavaScript函数的简单示例?](http:// stackoverflow.com/q/13806695/1048572)例如 – Bergi
也许这有帮助吗? http://stackoverflow.com/questions/21607692/understanding-the-event-loop – ecarrizo