【问题标题】:Function that returns a Promise calls itself in resolve返回 Promise 的函数在 resolve 中调用自身
【发布时间】:2022-06-11 01:21:57
【问题描述】:

我是 javascript 和 node.js 的初学者,如果这个问题被认为太简单,请原谅我。

我想知道,如果我有一个返回 Promise 的函数,并且在它的 resolve() 中它以某种递归方式再次调用相同的函数,如果它没有得到解决,这会导致堆栈溢出吗?

你可以想象它如下:

var someVariable = await myFunction(someInput)

async function myFunction(myInputValue) {

    return new Promise(function(resolve, reject) {

        // do some computation
        if (someCondition) {
            resolve(true)
            return
        } else {
            resolve(myFunction(myInputValue))
            return
        }
    })
}

我之所以问这个问题,是因为我注意到返回指令被执行了,这应该(在我看来)释放函数的上下文堆栈并避免出现堆栈溢出等问题。我是否遗漏了一些东西,然后我冒着问题的风险,或者我是对的,这可以被认为是非常安全的做法?

【问题讨论】:

  • 为什么是myFunction async?它永远不会 awaits ... 所以 async 是多余的
  • 测试是否会出现堆栈溢出...只需将if (someCondition) { 更改为if (false) { - 然后你会看到如果从未遇到someCondition 会发生什么 - 测试这样的事情如果只有一个人真正尝试,就可以如此简单
  • @Bravo 我放了async,因为在我的真实代码中它需要await,所以你也可以不在这里考虑它。顺便说一句,我试图以这种方式执行它并没有遇到任何麻烦,但我要求它确定。正如我所说,我是 node.js 的新手,所以如果有人肯定知道它,比我有更好的知识,我会觉得更安全。
  • 这就是实际代码与最小代码的问题......有时最小代码太少而无法提出合理的建议
  • @Bravo 是的,这是肯定的。但问题不在于此,因此在这种特殊情况下,当实际问题是关于 node.js 的函数堆栈上下文管理时,将我的整个代码放在上面是没有用的。

标签: javascript node.js recursion promise stack-overflow


【解决方案1】:

myFunction是一个async函数,所以你可以把它当成一个总是返回Promise的函数,你可以递归调用它。

resolvePromise constructor 中的 Promise 是安全的:

resolutionFunc value 参数可以是另一个 promise 对象,在这种情况下,promise 会动态插入到 promise 链中。

async function 返回 Promise 也是安全的:

异步函数的返回值隐式包装在 Promise.resolve 中 - 如果它本身还不是一个 Promise(如示例中所示)。

...Promise.resolve 被描述为返回:

使用给定值解析的Promise,或者作为值传递的承诺,如果该值是一个承诺对象。

但是:没有理由在 async 函数中使用 new Promiseasync 函数已经将它可以返回的任何内容包装在 Promise 中,因此您可以跳过explicit Promise construction antipattern 那里。

var someVariable = await myFunction(someInput)

async function myFunction(myInputValue) {
  // do some computation on myInputValue that awaits something

  if (someCondition) {
    return true;
  } else {
    return myFunction(someModificationOf(myInputValue));
  }
}

您仍然需要根据someCondition 以及您对myInputValue 所做的任何递归修改来检查此递归案例是否安全:如果您不退出递归案例,那么您可能 遇到堆栈溢出,或者您可能 耗尽堆内存或永远旋转。 (在async 函数中,the function runs synchronously up until the first await,但根据Promises/A+ 2.2.4 and ES6,Promise 处理程序始终使用否则为空的堆栈来调用。)

【讨论】:

    猜你喜欢
    • 2019-12-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-10
    • 2018-11-16
    • 2017-11-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多