据我所知,异步函数将它们的返回值隐式包装到一个 promise 中。这确实适用于每个属性,除了 Promises 本身。
async function f() {
return new Promise((res) => {
setTimeout(() => {
res("Why am I being unwrapped")
}, 1000)
})
}
(async () => {
console.log(await f())
})()
那些在返回之前会被打开。所以 await f()
实际上等待两个嵌套的 promise。
Note that this also works with explicitly createded Promises (
Promise.resolve(new Promise(...))
)
是否有好的方法来避免这种情况?我真的很想有一个没有像这样的 quickfix 的嵌套 Promise。
async function y() {
return {wrapped: new Promise((res) => {
setTimeout(() => {
res("Why am I being unwrapped")
}, 1000)
})}
}
(async () => {
console.log((await y()).wrapped)
})()
最佳答案
根据 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
关键字。 除非您await
它,否则您会得到原始的 Promise。
如此有效:
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()
包装所有但 Promise,如果您以某种方式给它一个 Promise,它会递归地解包。
你可以通过返回一些不是 Promise 的东西来做到这一点,就像你的例子一样,但这似乎违背了 Promises 的全部目的。
如果你有一个特定的问题,你试图解决它绝对需要一个延迟的 promise ,考虑返回一个函数而不是一些任意对象:
function f() {
return () => {
return new Promise((res) => {
setTimeout(() => {
res("I'll start as soon as you ask.")
}, 1000)
})
};
}
然后您可以调用 let p = f()
,然后在您想要获得实际 Promise 时调用 p()
。这就是 JavaScript 通常处理延迟执行的方式。
如果您想立即启动对 Promise 的执行,您仍然可以适应:
function f() {
const p = new Promise((res) => {
setTimeout(() => {
res("Already underway when requested.")
}, 1000)
})
return () => { p };
}
尽管通常最好尽可能避免使用这些技术,而且通常是这样。
关于javascript - JS : async function implicitly unwraps promise?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61762358/