Javascript 回调未等待上一个函数完成。

Javascript 回调未等待上一个函数完成。,javascript,Javascript,如果回调应该允许一个函数在调用另一个函数之前等待另一个函数完成,那么为什么以下操作不起作用 function doHomework(subject, callback) { setTimeout(function() { console.log(`Starting my ${subject} homework.`) }, 1000) callback() } function finishHomework() { console.log('Hom

如果回调应该允许一个函数在调用另一个函数之前等待另一个函数完成,那么为什么以下操作不起作用

function doHomework(subject, callback) {
    setTimeout(function() {
        console.log(`Starting my ${subject} homework.`)
    }, 1000)
    callback()
}

function finishHomework() {
    console.log('Homework Finished!')
}

doHomework('chemistry', finishHomework)
输出以下内容:

Homework Finished!
Starting my chemistry homework.

但它应该是另一种方式。为什么回调函数在调用之前不等待setTimeout完成?

A
callback
是将来执行的某个函数的名称,您的回调函数在调用函数
setTimeout
后立即执行

实际上,您要做的是在未来一秒钟内调用函数
finishHomeline
,因此,您必须将该
callback
放在函数
setTimeout
的处理程序中,如下所示:

函数(主题,回调){
setTimeout(函数(){
log(`Starting my${subject}作业。`);
//这取决于您的需要,在本例中为回调
//将在执行之前的所有逻辑后调用。
回调函数()
}, 1000)
}
函数finishHomegram(){
console.log('作业完成!')
}

dohomography(“化学”,finishhomography)
您需要了解JS的执行模型。由于JS打算在GUI中运行,因此它是事件驱动的,因此在事件循环中运行。这意味着主线程正在执行您的脚本,但其他线程可能在主线程排队的准备工作中工作

for (;;)
  if event = dequeueWork()
    handleEvent(event)
  else
    sleep(SOME_TIME)
在解释脚本时,JS引擎知道
doHome作业()
有一个超时事件注册。超时就像其他语言中的睡眠,但由于这是一个事件循环模型,我们无法阻止GUI。所以这个函数实际上是由后台线程处理的。当持续时间结束时,会通知主线程——这就是JS中处理所有IO的方式

理解了这一点,就很容易看到发生了什么:在注册超时事件之后立即启动回调

来自c-sharpcorner.com

要解决此问题,正如其他人所提到的,您需要在timeout的回调中调用回调:

函数(主题,回调){
log(`Starting my${subject}作业。`)
setTimeout(函数(){
回调();
}, 1000);
}
函数finishHomegram(){
console.log('作业完成!')
}

DoHomebook(“chemistry”,finishHomebook)
尝试阅读,因为您正在调用
回调
而不是
设置超时
回调。“为什么回调不等待setTimeout完成后再调用?”因为
setTimeout
(或任何异步代码)不是这样工作的。如果您希望A在B完成后发生,则必须在B告诉您A已完成时执行A。当
setTimeout
完成时,它调用传递给它的回调。建议注意:但是如果我将回调放在setTimeout内,那么就没有证据表明回调等待完成某些操作。在这种情况下,我的回调函数就像其他函数一样,按照编写的顺序被调用,但不等待任何事情完成。请仔细阅读我的答案或推荐的文章。如果您还有问题,我很乐意详细说明。如果我理解正确,您会想知道为什么您的函数不是异步的,而setTimeout是异步的。这是一个很好的问题。回调仅用于处理异步代码,但不定义异步代码。setTimeout是异步的开箱即用(由JSSTD库提供),就像XMLHttpRequest一样(正如您所指出的)。请仔细阅读我推荐的文章。另一方面,当您直接或间接使用异步函数时,调用方也被视为异步的。@控制论:从技术上讲,“回调”只是传递给另一个函数并由另一个函数调用的函数。传递给
数组#map
的函数也是回调函数(即
[1,2,3].map(x=>x+1)
)。无论何时/如何执行,都没有任何含义。这取决于接收回调的函数。@controlnetic Yes确切地说:)最后一件事(为了澄清,您不必猜测上一个异步函数何时完成,因为您总是可以在其回调中执行副作用(如在上面的
setTimeout
回调中调用
callback()
)。通过这种方式,您可以在不阻塞主线程的情况下强制执行命令。不幸的是,在callbacks中的callbacks中调用callbacks等等,被称为callbackhell,这是不明智的。承诺是缓解这种情况的标准抽象(通过链接
then
s)。