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.
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.
So effectively:
function f() {
return new Promise((res) => {
setTimeout(() => {
res("Might be wrappers on some of you, but not on me!")
}, 1000)
})
}
(async () => {
console.log(f())
})()
Which gives you output like:
Promise { <pending> }
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.
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.
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)
})
};
}
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.
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.