2

请帮助我理解这一点。

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

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

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

所以如果我用回调调用methodA,执行将不得不等到方法返回,这不会是异步的,对吧?

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

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

4

3 回答 3

5

JavaScript 中的回调不会隐式添加异步行为。当调用回调函数时,它会立即运行就像普通函数一样。(其实回调函数只是一个普通的函数……)

因此,无法确定示例中回调的执行何时将与其他方法相关联运行(除非它不能在methodA被调用之前运行)——它可以通过单击methodAmethodB单击调用以后,或者根本没有。(但是,除非出现异常——或者其中一个函数调用了其他函数之一——否则methodA将在之前运行,然后在之前methodB运行methodC;如果methodA抛出异常,则既methodB不会也methodC不会被调用)。

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

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

这就是为什么while (true) {}会使浏览器页面冻结并阻止处理按钮事件处理程序的原因。

快乐编码。


示例案例(jsfiddle 演示):

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")
}))

警告:Firefox 4 (4.0.1) 和上面的代码似乎存在问题。虽然它按演示工作,但如果超时低于约 800 毫秒,则预期顺序与实际顺序不同。我已经发布了:异步计时器事件在 Firefox 4 中同步运行(“错误”)?所以希望会有一些解决方案。该行为在 Firefox 3、IE 9 和 Chrome 11 中按预期工作。

于 2011-05-21T20:04:02.127 回答
1
function main() {
   methodA(function callback(){...});
   methodB();
   methodC();
}

假设回调没有立即执行。

执行顺序:

  • 方法A
  • 方法B
  • 方法C
  • ...直到堆栈为空的其他事情
  • 打回来
于 2011-05-21T20:02:18.767 回答
0

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

如果你有类似的东西:

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

然后回调将在您调用时调用methodA(function(){...})

于 2011-05-21T20:07:08.457 回答