Javascript 回调函数未按预期执行
Javascript callback function not executing as intended
根据这个 Whosebug ,
functions passed as parameters are always callbacks, even if the intention is that the function is called synchronously...
而且我已经了解了事件循环机制,它基本上说回调函数被推入等待队列并在同步代码完成(堆栈为空)后执行,但是在下面的代码中
function myfun(a, b, callback) {
console.log(a);
callback();
console.log(b);
}
function cb() {console.log('hi')}
myfun(1, 2, cb) // result: 1 hi 2
结果不是我预期的 1 2 hi
,从中我推断只有触发一些 'event signal' 的回调函数,如 setTimeout
才会被推入这样的队列,但我不能'找不到具体的参考资料来支持它?
并不一定意味着每一个callback
都是asynchronous
一定要放入某个task queue
执行一次synchronous
个代码段(调用堆栈为空)完成。处理 Promise
的回调函数是 task queue
的候选函数。例如你的情况; cb
函数简单地以同步方式运行;这样结果就是 1 hi 2
如您所指;但是,如果我们按如下方式修改您的代码:
function myfun(a, b, callback) {
console.log(a);
window.setTimeout(callback, 0);
console.log(b);
}
function cb() {
console.log('hi');
}
myfun(1, 2, cb) // result: 1 2 hi
这将导致 1 2 hi
。即使我将超时设置为 0
毫秒; cb
函数将在 myfun
函数中的第二个 console.log
之后输出。我建议您查看 MDN and this good explanation 的调用堆栈、事件循环和任务队列。希望这会有所帮助。
"Callbacks" 通常与异步进程结合使用,例如 ajax 请求或附加到 ui 的事件处理程序。在这些情况下,我们称它们为 "callbacks",因为它们需要在其他事情之后执行,并且很明显,在异步过程完成或触发后,程序的逻辑将在哪里恢复这个 "call" "back" 这里。
您可以使用 setTimeout() 添加到事件循环堆栈。使用承诺,您可以在等待异步过程完成时调用事件循环中的堆栈。
您的代码没有做任何事情来中断代码的同步流。这个片段展示了即使我们添加了一个应该延迟操作的超时 0,我们仍然可以等待一个允许事件循环堆栈到 运行.
的承诺。
function myfun(a, b, callback) {
console.log(a);
callback();
console.log(b);
}
function cb() {
console.log('hi')
}
myfun(1, 2, cb) // result: 1 hi 2
// same behavior as above
function myStaticFun() {
console.log(1);
cb();
console.log(2);
}
myStaticFun();
// now same as before using a promise to wait a moment and the event loop stack is invoked during the pause
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
async function myEventLoopInvokingFun(a, b, callback) {
console.log(a);
setTimeout(callback, 0)
await sleep(0);
console.log(b);
}
myEventLoopInvokingFun(1, 2, cb);
根据这个 Whosebug
functions passed as parameters are always callbacks, even if the intention is that the function is called synchronously...
而且我已经了解了事件循环机制,它基本上说回调函数被推入等待队列并在同步代码完成(堆栈为空)后执行,但是在下面的代码中
function myfun(a, b, callback) {
console.log(a);
callback();
console.log(b);
}
function cb() {console.log('hi')}
myfun(1, 2, cb) // result: 1 hi 2
结果不是我预期的 1 2 hi
,从中我推断只有触发一些 'event signal' 的回调函数,如 setTimeout
才会被推入这样的队列,但我不能'找不到具体的参考资料来支持它?
并不一定意味着每一个callback
都是asynchronous
一定要放入某个task queue
执行一次synchronous
个代码段(调用堆栈为空)完成。处理 Promise
的回调函数是 task queue
的候选函数。例如你的情况; cb
函数简单地以同步方式运行;这样结果就是 1 hi 2
如您所指;但是,如果我们按如下方式修改您的代码:
function myfun(a, b, callback) {
console.log(a);
window.setTimeout(callback, 0);
console.log(b);
}
function cb() {
console.log('hi');
}
myfun(1, 2, cb) // result: 1 2 hi
这将导致 1 2 hi
。即使我将超时设置为 0
毫秒; cb
函数将在 myfun
函数中的第二个 console.log
之后输出。我建议您查看 MDN and this good explanation 的调用堆栈、事件循环和任务队列。希望这会有所帮助。
"Callbacks" 通常与异步进程结合使用,例如 ajax 请求或附加到 ui 的事件处理程序。在这些情况下,我们称它们为 "callbacks",因为它们需要在其他事情之后执行,并且很明显,在异步过程完成或触发后,程序的逻辑将在哪里恢复这个 "call" "back" 这里。
您可以使用 setTimeout() 添加到事件循环堆栈。使用承诺,您可以在等待异步过程完成时调用事件循环中的堆栈。
您的代码没有做任何事情来中断代码的同步流。这个片段展示了即使我们添加了一个应该延迟操作的超时 0,我们仍然可以等待一个允许事件循环堆栈到 运行.
的承诺。function myfun(a, b, callback) {
console.log(a);
callback();
console.log(b);
}
function cb() {
console.log('hi')
}
myfun(1, 2, cb) // result: 1 hi 2
// same behavior as above
function myStaticFun() {
console.log(1);
cb();
console.log(2);
}
myStaticFun();
// now same as before using a promise to wait a moment and the event loop stack is invoked during the pause
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
async function myEventLoopInvokingFun(a, b, callback) {
console.log(a);
setTimeout(callback, 0)
await sleep(0);
console.log(b);
}
myEventLoopInvokingFun(1, 2, cb);