回调不等待上一个功能完成。

时间:2018-11-15 01:08:14

标签: javascript

如果应该使回调允许一个功能在被调用之前等待另一个功能完成,为什么以下功能不起作用?

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完成才被调用?

2 个答案:

答案 0 :(得分:1)

您需要了解JS的执行模型。由于JS旨在在GUI中运行,因此它是事件驱动的,因此在事件循环中运行。这意味着主线程正在执行您的脚本,但是其他线程可以在主线程排队的就绪工作上工作。

for (;;)
  if event = dequeueWork()
    handleEvent(event)
  else
    sleep(SOME_TIME)

解释了脚本后,JS引擎会知道doHomework()具有超时事件注册。超时就像其他语言的睡眠一样,但是由于这是一个事件循环模型,因此我们无法阻止GUI。因此,此功能实际上是由后台线程处理的。持续时间过去后,将通知主线程-这是在JS中处理所有IO的方式。

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

来自c-sharpcorner.com

要解决此问题,就像其他人提到的那样,您需要在超时的回调中调用该回调:

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

    setTimeout(function() {
        callback();
    }, 1000);
}

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

doHomework('chemistry', finishHomework)

当然,我们所有人都还不够幸运,无法在开始1秒后完成作业;)

有用的资源:

答案 1 :(得分:0)

callback是将来执行的某事物的名称,您的回调将来不会执行,而是在调用函数setTimeout之后立即执行。

您真正想做的是将来一秒钟调用函数finishHomework,因此,您必须将callback放在函数setTimeout的处理程序中,如下所示:

function doHomework(subject, callback) {
    setTimeout(function() {
        console.log(`Starting my ${subject} homework.`);
        // Here depends of your needs, in this case the callback
        // will be called after all the previous logic is executed.
        callback()
    }, 1000)

}

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

doHomework('chemistry', finishHomework)