JS:异步函数隐式地解开承诺? [英] JS: async function implicitly unwraps promise?

查看:39
本文介绍了JS:异步函数隐式地解开承诺?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

据我所知,异步函数将它们的返回值隐式包装到一个 promise 中.这确实适用于每个属性,除了 Promise 本身.

To the best of my knowledge async functions wrap their returned value into a promise implicitly. This does work for every property, except Promises themselfs.

async function f() {
  return new Promise((res) => {
    setTimeout(() => {
      res("Why am I being unwrapped")
    }, 1000)
  })
}

(async () => {
  console.log(await f())
})()

那些在返回之前会被打开.所以 await f() 实际上等待两个嵌套的 promise.

Those get unwrapped before being returned. So that await f() actually awaits two nested promises.

请注意,这也适用于显式创建的 Promise (Promise.resolve(new Promise(...)))

Note that this also works with explicitly createded Promises (Promise.resolve(new Promise(...)))

有没有好的方法来避免这种情况?我真的很想拥有一个嵌套的 Promise,而没有像这样的快速修复.

Is there a good way to avoid this? I would really like to have a nested Promise without a quickfix like so.

async function y() {
  return {wrapped: new Promise((res) => {
    setTimeout(() => {
      res("Why am I being unwrapped")
    }, 1000)
  })}
}

(async () => {
  console.log((await y()).wrapped)
})()

沙盒

推荐答案

根据 关于async 函数的 MDN 文档:

As per the MDN documentation on async functions:

异步函数总是返回一个承诺.如果异步函数的返回值不是明确的承诺,它将被隐式包装在承诺中.

Async functions always return a promise. If the return value of an async function is not explicitly a promise, it will be implicitly wrapped in a promise.

换句话说,由于您返回的是 Promise,因此它不会被包装.如果你想重新包装它,你可以,但你也可以去掉具有类似效果的 async 关键字.你会得到原始的 Promise 除非await它.

In other words, since you're returning a Promise it does not get wrapped. If you want to re-wrap it you could, but you could also strip the async keyword which has a similar effect. You get the raw Promise back unless you await it.

如此有效:

function f() {
  return new Promise((res) => {
    setTimeout(() => {
      res("Might be wrappers on some of you, but not on me!")
    }, 1000)
  })
}

(async () => {
  console.log(f())
})()

它给你的输出如下:

Promise { <pending> }

如果目标是让 Promise 返回原始 Promise,那么您将与 Promise 系统设计要做的一切作斗争,即在发现 Promise 时自动解包.Promise.resolve() 包装了所有 Promises,如果你以某种方式给它一个Promise,它会递归地解开它.

If the goal is to have a Promise that returns a raw Promise then you're going to be fighting against everything that the Promise system is designed to do, namely automatically unwrap Promises as they're discovered. Promise.resolve() wraps everything but Promises, and if you give it a Promise somehow, it goes about unwrapping that recursively.

您可以通过返回一些不是 Promise 的东西来做到这一点,就像在您的示例中一样,但这似乎违背了 Promise 的全部目的.

You can do this by returning something that is not a Promise, like in your example, but that does seem to defeat the entire purpose of Promises.

如果你有一个特定的问题,你正在尝试解决这个绝对需要延迟 Promise 的问题,请考虑返回一个函数而不是某个任意对象:

If you have a particular problem you're trying to solve that absolutely necessitates a deferred Promise, consider returning a function instead of some arbitrary object:

function f() {
  return () => {
    return new Promise((res) => {
      setTimeout(() => {
        res("I'll start as soon as you ask.")
      }, 1000)
    })
  };
}

然后,当您想要获得实际的 Promise 时,您可以调用 let p = f() 和以后的 p().这就是 JavaScript 通常处理延迟执行的方式.

Then you can call let p = f() and later p() when you want to get an actual Promise. This is how JavaScript normally handles deferred execution.

如果你想立即启动对 Promise 的执行,你仍然可以适应:

If you want to initiate the execution on the Promise immediately, you can still accommodate that:

function f() {
  const p = new Promise((res) => {
    setTimeout(() => {
      res("Already underway when requested.")
    }, 1000)
  })

  return () => { p };
}

不过,如果可能的话,通常最好避免使用这些技术,而且通常确实如此.

Though these sorts of techniques are usually best avoided if at all possible, and usually they are.

这篇关于JS:异步函数隐式地解开承诺?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆