2016-08-24 44 views
2

我读过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 
}; 

只有我见过真正的异步功能与承诺,并承诺多在那里我可以,例如,当动画结束了加载其他数据。我希望能够帮助我们更好地理解传统回调是否实际上是异步的。具体的例子帮助。

+1

“回调”实际上只是一个函数,您将其作为参数传递给另一个函数,以便其他函数可以调用它,这个进程* *可以*都是同步的 - 它实际上取决于其他函数功能在做。但即使在像Ajax这样的异步情况下,它不是异步的回调函数本身,它最终会调用它是异步的。在你的例子中,'doThat()'不会等待 - 它是等待调用'doThat()'的其他代码(你的'doThat()'定义也是无效的)。 – nnnnnn

+0

你可能想看看[所有的javascript回调是异步的吗?如果不是,我怎么知道哪些是?](http://stackoverflow.com/q/19083357/1048572)的一般问题和[什么是异步JavaScript函数的简单示例?](http:// stackoverflow.com/q/13806695/1048572)例如 – Bergi

+0

也许这有帮助吗? http://stackoverflow.com/questions/21607692/understanding-the-event-loop – ecarrizo

回答

1

例如,我可以在动画结束时加载其他数据。

这正是您可以对您的代码执行的操作。请注意,您可以在等待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?

+0

这是一个明确的解释。谢谢! – Growler

4

与定义开始:

不同步,在计算机编程,是指独立于主程序流程和方法来处理此类事件的事件的发生。这些可能是“外部”事件,例如信号的到来,或者是与程序执行同时发生的程序引发的行为,而不会阻止程序等待结果。

- Davies,Alex(2012)。在C#5.0中的异步,通过维基百科对Asynchrony (computer programming)

在JavaScript的情况下,它的工作原理是这样的(简化):有一个等待主线程(并且只有)执行的任务队列。加载脚本时,它是放置在该队列上的任务。一个任务运行直到它退出,并且其他任务都不会中断它。但是,任务可能导致其他任务被放置在队列中。当一个任务完成时,队列上的下一个任务开始。如果队列为空,则后来进入队列的第一个任务将立即执行。

的任务进入队列,除了是脚本的主要任务主要方式来解析和执行:触发事件将会把有关任务队列事件注册处理程序,并达到通过setTimeoutsetInterval预定时间将关联的任务放置在任务队列中。

在JavaScript方面,该相同任务(“主程序流程”)内执行的一切被说成是同步。在未来任务中执行的所有内容都称为异步。另一种说法是 - 如果下一条语句在回调之前执行,则它是异步的;如果下一条语句在回调后执行,则它是同步的。

$.get(opts, callback)是异步调用,因为执行功能callback的任务将在onreadystatechange事件触发时置于任务队列中。如果你有一个后面的声明,它会先执行;只有在任务完成后,由于AJAX调用更新而进入任务队列的任务才有机会运行。

相比之下,$.each(collection, callback)是一个同步调用,因为callback将从each函数直接调用,而不必退出当前的任务,而不会自己反正产生任何额外任务(当然不是callback可以产生额外的任务)。下一个陈述将不得不等到each完成遍历collection的每个元素。

请注意,承诺仅仅是对此机制的封装。所有你可以用承诺做的事情,你可以在没有它们的情况下做,只是代码不会很漂亮和清晰。

相关问题