异步行为。递归setTimeout没有完成

时间:2018-05-25 09:58:52

标签: javascript asynchronous settimeout

在执行下一行代码之前,我不知道为什么我的程序没有完成递归函数。

console.clear();
var a = 1;

function logA() {
  if (a<11) {
    console.log(a);
    a++;
    setTimeout(logA, 100);
  }
  else {
    return;
  }
}

logA();
console.log("after set timeout");

样品: https://jsbin.com/moyanudeki/edit?js,console

堆栈中发生了什么?

3 个答案:

答案 0 :(得分:2)

这里没有递归。 setTimeout,顾名思义,在设定的时间(在这种情况下为100ms)到期后,为异步执行安排一个函数。这并不能阻止当前批次的代码运行。

即。 logA()将返回,控制台打印"after set timeout",然后VM等待100ms到期。当发生这种情况时,它会执行logA(),再次安排自己,依此类推。

为了清楚起见,这个将是递归:

console.clear();
var a = 1;

function logA() {
  if (a<11) {
    console.log(a);
    a++;
    logA();
  }
  else {
    return;
  }
}

logA();
console.log("after recursion");

答案 1 :(得分:1)

第一次调用logA()函数时,if块按预期执行。第一次调用setTimeout(logA, 100);

在Javascript setTimeout()中异步运行,因此它将在堆栈中等待100ms,并执行下一个console.log("after set timeout");语句。执行此第一次超时后的logA函数,触发一次超时等等。

所以你的输出符合预期:

1
"after set timeout"
2
3
4
5
6
7
8
9
10

答案 2 :(得分:1)

也可能有兴趣了解堆栈在javascript中的行为是如何理解事件循环。在javascript中,首先清空堆栈,然后执行异步回调,这些回调堆叠在事件队列中。

在您的示例中,我们有以下代码:

function test () {
  console.log('first log');
}

setTimeout(test, 0);

console.log('last log');

现在,在事件队列中传递函数对象测试。清除堆栈后,此功能将被执行。

但是如果你像这样执行directy函数:

    function test () {
      console.log('first log');
    }

    setTimeout(test(), 0);

    console.log('last log');

现在将直接执行功能代码,并且该功能不会在事件队列中结束。

希望这很有帮助