zzr*_*zrv 2 javascript asynchronous node.js promise async-await
据我所知,异步函数将其返回值隐式包装到承诺中。这确实适用于所有属性,除了 Promise 本身。
async function f() {
return new Promise((res) => {
setTimeout(() => {
res("Why am I being unwrapped")
}, 1000)
})
}
(async () => {
console.log(await f())
})()
Run Code Online (Sandbox Code Playgroud)
那些在退回之前会被拆开。所以这await f()实际上等待着两个嵌套的承诺。
请注意,这也适用于显式创建的 Promises (
Promise.resolve(new Promise(...)))
有没有好的办法避免这种情况呢?我真的很想有一个嵌套的 Promise,而不需要像这样的快速修复。
async function y() {
return {wrapped: new Promise((res) => {
setTimeout(() => {
res("Why am I being unwrapped")
}, 1000)
})}
}
(async () => {
console.log((await y()).wrapped)
})()
Run Code Online (Sandbox Code Playgroud)
异步函数总是返回一个承诺。如果异步函数的返回值不是显式的 Promise,它将隐式包装在 Promise 中。
换句话说,由于您返回的是 Promise,所以它不会被包装。如果你想重新包装它,你可以,但你也可以删除async具有类似效果的关键字。除非你这样做,否则你会得到原始的 Promise await。
如此有效:
function f() {
return new Promise((res) => {
setTimeout(() => {
res("Might be wrappers on some of you, but not on me!")
}, 1000)
})
}
(async () => {
console.log(f())
})()
Run Code Online (Sandbox Code Playgroud)
这会给你这样的输出:
Promise { <pending> }
Run Code Online (Sandbox Code Playgroud)
如果目标是有一个返回原始 Promise 的 Promise,那么您将与 Promise 系统设计要做的所有事情作斗争,即在发现 Promise 时自动解开它们。Promise.resolve()包装除Promise之外的所有内容,如果您以某种方式给它一个 Promise,它就会递归地展开它。
您可以通过返回一些不是 Promise 的东西来做到这一点,就像在您的示例中一样,但这似乎确实违背了 Promise 的整个目的。
如果您正在尝试解决一个绝对需要延迟 Promise 的特定问题,请考虑返回一个函数而不是某个任意对象:
function f() {
return () => {
return new Promise((res) => {
setTimeout(() => {
res("I'll start as soon as you ask.")
}, 1000)
})
};
}
Run Code Online (Sandbox Code Playgroud)
然后你可以打电话let p = f(),稍后p()当你想得到一个实际的 Promise 时。这就是 JavaScript 通常处理延迟执行的方式。
如果你想立即启动 Promise 的执行,你仍然可以满足:
function f() {
const p = new Promise((res) => {
setTimeout(() => {
res("Already underway when requested.")
}, 1000)
})
return () => { p };
}
Run Code Online (Sandbox Code Playgroud)
不过,如果可能的话,通常最好避免使用这些技术,而且通常也是如此。