使用setTimeout()时调用堆栈

时间:2015-03-31 10:27:33

标签: javascript

我对setTimeout感到有点困惑。我想确认以下代码的输出是否一直是:

inside abc
inside sample

代码:

function abc() {
    xyz();

    // interactions and modifications in DOM 
    $("#id1").append("something");
    $("#id2").val("set something");
    $("#id3").after("create some dynamic element");
    // 10 to 20 interaction more...

    console.log('inside abc');
}

function xyz() {
    setTimeout(function() {
        sample();
    },0);  
}

function sample() {
    console.log('inside sample')
}

如果有人可以通过调用堆栈解释整个流程,那将会很棒。

3 个答案:

答案 0 :(得分:3)

是的,它总会有输出。

在执行上下文清除之前,将不会调用setTimeout内的回调 - 即当前正在执行的代码序列已完成。

这意味着即使你做了

setTimeout(function () { console.log("1 second!"); }, 1000);

var start = +new Date();
while ((+new Date()) - start < 5000) {}

1 second!不会在5秒后记录。

答案 1 :(得分:3)

完成当前执行块后,

setTimeout()将异步运行。所以输出应始终相同:

inside abc
inside sample

Javascript在内部管理所有异步任务的事件队列。每次在完成当前执行块后检查其异步队列。

答案 2 :(得分:2)

是的,控制台输出将始终相同。 setTimeout的回调函数在清除调用它的上下文后异步执行。调用setTimeout时,它会将其回调函数放在堆栈上并返回当前执行上下文。完成后(在您的示例中,当abc完全执行时),将执行回调函数,在您的示例中,它基本上会立即调用sample。所以你的代码输出永远不会有所不同。

如果你在调用xyz之前在abc中的某处放置了一个更长的setTimeout函数,那么可以看到setTimeout的回调本身是异步执行的这一事实:

function abc() {
    setTimeout(function(){
        console.log('wait')
    },1000);
    xyz();
    console.log('inside abc');
}
function xyz() {
    setTimeout(function(){
        sample();
    } ,0);  
}
function sample() {
    console.log('inside sample');
}
abc();    

...您的控制台将记录:

inside abc
inside sample
wait

要保持样本的执行,直到更长的超时完成,您需要将setTimeout调用样本放在更长的setTimeout中。

如果setTimeout的回调行为不同,很可能是由于意外传递了函数调用而不是函数指针,如下所示:

setTimeout(sample(),0);

而不是

setTimeout(sample,0)

此外,如果您不知道(或其他人),您可以添加

debugger;

在您的Javascript代码中的任何位置,然后使用开发工具运行代码以查看当时的callstack(在Chrome中,它位于&#39; Sources&#39;右侧面板中)。