问题
Given the following two implementations (in ES6 / NodeJS)
async TestFunc() {
return new Promise((resolve,reject) => {
...
});
}
and
TestFunc() {
return new Promise((resolve,reject) => {
...
});
}
Is there any difference in behavior if I were to call either of these functions like so?
await TestFunc();
I would assume that the first (async) implementation would return a promise, and we would be awaiting that to return another promise, whereas the latter (synchronous) implementation would return the promise, which then would get awaited. However, they both work as expected, leaving me a bit confused.
回答1:
An async function returns a promise that will be resolved by the value returned by a return
statement executed in the function body (or resolved with undefined
if returning after executing the last line of function code).
Resolving a promise with a promise makes the resolved promise take on the settled state and value of the resolving promise when and if it becomes settled.
So always synchronously returning a promise P from an async function body on first call immediately links the outcome of the promise returned by calling the async function to the outcome of P. This is an unnecessary step for a synchronously returned promise and the async
declaration of the function is not necessary.
If TestFunc
is an async function, for
await TestFunc();
the operand of the await
operator is the promise generated by calling the async
function. This promise will be settled by a promise returned in function body code.
If TestFunc
is not an async function, for
await TestFunc();
the operand of the await
operator is the promise constructed and returned by the TestFunc
. The effective difference is that TestFunc
can't internally use the await
operator without changing it back to an async function.
回答2:
function TestFunc() {
return new Promise( resolve => {
setTimeout(()=>{ resolve(42) }, 5000 );
});
}
Alright! We have imported @w0f's asynchronous function and have just decided that we want to use it with async/await.
However, one assumption is wrong: That we would need to change @w0f's function to do so.
Instead, we only use the async
keyword to allow the use of await
inside our own function:
async function run(){
const value = await TestFunc();
// Now we can use the value just as if was a normal variable declaration.
const total = value + 14;
}
run();
The same thing with promises would be:
const promise = TestFunc();
promise.then(value => {
const total = value + 14;
});
And anyone new to promises would think "Okay that doesn't look so bad, now we only need to unwrap the value from the promise!". But alas...
const promise = TestFunc();
let total;
promise.then(value => {
total = value + 14;
});
// ...it's not possible to unwrap a value from a promise while
// also knowing when the value has resolved - other than checking every now and then:
console.log( total ); // undefined
wait( 3000 ); // wait is a synchronous wait to be implemented by the reader :p
console.log( total ); // undefined
wait( 3000 );
console.log( total ); // 56, yay!
So perhaps you spend a few months to invent some clever and intricate code to check if a value has resolved or not. Congratulations, you have just reinvented promises!
And that's why await is so neat. You are effectively operating on a promise-wrapped value but async/await makes it look like a normal value.
来源:https://stackoverflow.com/questions/50918694/returning-promise-with-an-async-function