Javascript中的异步性背后的东西 - 事件驱动系统

时间:2011-05-21 19:58:39

标签: javascript asynchronous callback event-driven

请帮助我理解这一点。

你有一个调用几种方法的函数:

function() {
   methodA(function(){...});
   methodB();
   methodC();
}

从没有回调或匿名函数的语言中,我习惯了这样一个事实,即在方法返回之前执行不会继续。

因此,如果我使用回调调用methodA,则执行必须等到方法返回时才会异步,对吧?

因此,例如,我可以将回调存储到某个对象并让methodA返回。然后执行methodB和methodC。当用户单击按钮时,某个处理程序会执行回调?

我得出的结论是,与java或python(不涉及多线程)相比,javascript没有任何异步....因为在java中,回调不是闭包/匿名方法,而是具有“执行“方法,它将完全相同,只是有点复杂......当然有这个特定于DOM的JS事件系统

3 个答案:

答案 0 :(得分:5)

JavaScript中的回调不会隐式添加异步行为。当调用回调函数时,它正常运行然后,就像正常函数一样。 (实际上,回调函数 只是一个正常的函数......)

因此,不可能确定示例中回调的执行何时与其他方法相关运行(除了它不能在methodA之前运行被调用) - 可以从methodAmethodB或稍后点击,或根本不调用。 (但是,除非有例外 - 或者其中一个函数调用其他函数之一 - 然后methodA将在methodB之前运行,而methodC将在methodA之前运行;如果methodB提出异常,然后调用methodCwhile (true) {}

添加异步行为是异步事件源,例如计时器事件或UI操作,例如按钮单击。

但是,请务必记住Javascript没有或支持线程。在触发新的异步事件之前,Javascript必须“停止”(执行必须从异步事件源调用的回调函数返回)。 (异步事件排队[视情况而定],因此如果另一个回调执行时间太长,定时器事件将不会“丢失”。)

这就是为什么function invokeNow(callback) { // nothing asynchronous going on here. // the callback is invoked right now and the result is returned. return callback() } alert(invokeNow(function () { return "Hello world!" })) function doLater(callback) { // setup an asynchronous event setTimeout(callback, 1000) return "It isn't 'later' yet!" } alert(doLater(function () { alert("Later!") // note that this is running in the callback from the previous // timer event. if this code was below the outer alert then // it wouldn't have allowed the first timer callback to have occurred // until the blocking while was complete alert(doLater(function () { alert("I still ran!") })) var end = (+new Date) + 4000 while ((+new Date) < end) { /* wait */ } alert("I am done waiting") })) 会使浏览器页面冻结并阻止处理按钮事件处理程序的原因。

快乐的编码。


示例案例(jsfiddle demo):

{{1}}

警告:Firefox 4(4.0.1)和上面的代码似乎存在问题。虽然它的工作原理如下所示,但如果超时低于约800毫秒,则预期的顺序与实际顺序不同。我发布了SO: Asynchronous timer event running synchronously (“buggy”) in Firefox 4?,希望能有一些解决方案。该行为在Firefox 3,IE 9和Chrome 11中按预期工作。

答案 1 :(得分:1)

function main() {
   methodA(function callback(){...});
   methodB();
   methodC();
}

假设没有立即执行回调。

执行顺序:

  • 了methodA
  • 的methodB
  • methodC
  • ...其他东西,直到堆栈为空
  • 回调

答案 2 :(得分:0)

Javascript是顺序的,除非您使用setIntervalsetTimeout,或使用回调或使用onload向服务器发出请求。不确定还有其他情况。

如果你有类似的话:

function methodA(fn){
  ...
  fn();
}

然后,当您致电methodA(function(){...})

时,系统会调用回叫