JavaScript 中的回调不会隐式添加异步行为。当调用回调函数时,它会立即运行,就像普通函数一样。(其实回调函数只是一个普通的函数……)
因此,无法确定示例中回调的执行何时将与其他方法相关联运行(除非它不能在methodA
被调用之前运行)——它可以通过单击methodA
或methodB
单击调用以后,或者根本没有。(但是,除非出现异常——或者其中一个函数调用了其他函数之一——否则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 中按预期工作。