javascript - 为什么 Javascript 中的递归异步函数会导致堆栈溢出?

标签 javascript recursion promise async-await stack-overflow

考虑这个片段:

function f() {
  return new Promise((resolve, reject) => {
    f().then(() => {
      resolve();
    });
  });
}

f();

也可以这样写:

async function f() {
  return await f();
}

f();

如果您运行给定的两个代码中的任何一个,您将遇到此错误:

(node:23197) UnhandledPromiseRejectionWarning: RangeError: Maximum call stack size exceeded

我的问题是为什么?在回答我的问题之前,请考虑我的论点:

我了解递归的概念以及如果没有停止条件它如何导致堆栈溢出。但我在这里的论点是,一旦第一个 f(); 被执行,它将返回一个 Promise 并且它退出堆栈,所以这个递归不应该面临任何堆栈溢出.对我来说,这应该与以下行为相同:

while (1) {}

当然,如果我这样写,就搞定了:

function f() {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      f().then(() => {
        resolve();
      });
    }, 0);
  });
}

f();

这是一个不同的故事,我没有问题。

[更新]

糟糕,我忘了说我正在服务器端使用 node v8.10.0 进行测试。

最佳答案

为什么你不认为它会导致无限递归? promise 的构造函数递归调用 f,因此 promise 永远不会构造,因为在构造 promise 之前会发生无限递归循环。

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise

来自上面的链接

执行器函数由 Promise 实现立即执行,传递 resolve 和 reject 函数(执行器在 Promise 构造函数甚至返回创建的对象之前被调用)。

关于javascript - 为什么 Javascript 中的递归异步函数会导致堆栈溢出?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56879005/

相关文章:

javascript - 随机ID功能。通过 prompt() 得到 ID 的长度和 Id 的数量

Python递归和列表

javascript - Twitter Bootstrap 轮播中的交互式 JavaScript 失败

javascript - 为什么 Angular 在回调函数中返回一个函数?

javascript - 如何使用可以启动/停止的递归函数编写应用程序

regex - 条件语句可以用来配对平衡组元素吗?

mongoose - 何时使用 denodeify/nfbind 与 nfcall/ninvoke

Javascript promise 在我的情况下不起作用

swift - Swift 和 Spring 中的链接动画无法正常工作

javascript - 组件指令中的 $destroy