[英]How to await an asynchronous function?
My case:我的情况:
let waiting = function () { return new Promise(resolve => { console.log('awaiting...'); setTimeout(function () { resolve(); }, 1000) }); }; let waitingAsync = async function () { console.log('start...'); await waiting(); console.log('stop...'); }; waitingAsync(); console.log('done...');
There are 2 things I don't understand in the code:代码中有两件事我不明白:
The first:首先:
await waiting();
waiting
is a synchronous function (because it doesn't have async
keyword). waiting
是一个同步函数(因为它没有async
关键字)。 So, why can I await a synchronous function?那么,为什么我可以等待一个同步函数呢?
The second:第二:
Why couldn't done...
message be awaited after completing waitingAsync
function?为什么无法
done...
完成waitingAsync
函数后等待消息?
And main question: waitingAsync
is an asynchronous function, why is await
keyword not required when calling it?主要问题:
waitingAsync
是一个异步函数,为什么调用它时不需要await
关键字? Just waitingAsync()
instead of await waitingAsync()
.只是
waitingAsync()
而不是await waitingAsync()
。
If I can await waitingAsync()
, done...
message would be printed last.如果我可以 await
waitingAsync()
, done...
消息将最后打印。
This isn't a function but a value that it returns which is awaited with await
statement.这不是函数,而是它返回的值,该值由
await
语句await
。
async
and normal functions aren't different to the caller. async
和普通函数与调用者没有什么不同。 async
just returns a promise without returning it explicitly when being called. async
在被调用时只返回一个承诺而不明确返回它。 The result of waitingAsync()
call is a promise. waitingAsync()
调用的结果是一个承诺。 The result of waiting()
call is a promise, too, so it isn't 'synchronous'. waiting()
调用的结果也是一个承诺,所以它不是“同步的”。
According to the spec , both promises and non-promises can be await
ed.根据规范,promises 和 non-promises 都可以
await
。 Non-promises are converted to promises with Promise.resolve()
.使用
Promise.resolve()
将非承诺转换为承诺。
console.log('done...')
can't be awaited because it isn't called inside async
function. console.log('done...')
不能等待,因为它不是在async
函数中调用的。 And it doesn't have to be await
ed because it doesn't return a promise but undefined
.而且它不必是
await
ed,因为它不返回 promise 而是undefined
。 await
ing it would be possible within async
function. await
在async
函数中是可能的。 These await
usages are equal and equally useless, all they do is 1 tick delay:这些
await
用法是相同且同样无用的,它们所做的只是 1 个滴答延迟:
async function ... {
...
await console.log('done...');
}
async function ... {
...
console.log('done...');
await undefined;
}
async function ... {
...
await Promise.resolve(console.log('done...'));
}
A async
function does return a promise or, when it uses the await
keyword, it must wait for a asynchronous function, being a Promise or another async
function. async
函数确实会返回一个承诺,或者,当它使用await
关键字时,它必须等待一个异步函数,即一个 Promise 或另一个async
函数。 In your code, waiting()
is a function that returns a Promise.在您的代码中,
waiting()
是一个返回 Promise 的函数。 Then, await waiting()
is correct (since it is waiting for a asynchronous function).然后,
await waiting()
是正确的(因为它正在等待一个异步函数)。
An async
function is called as another basic functions is called.在调用另一个基本函数时调用
async
函数。 You may mark a function as async when you desire operate it as an asynchronous function and using the 'await' keyword.当您希望将函数作为异步函数操作并使用“await”关键字时,您可以将其标记为异步。 The 'done...' is printed because when you call
asyncFunction()
, it must await
until waiting promise
is finished.打印 'done...' 是因为当您调用
asyncFunction()
,它必须await
直到waiting promise
完成。 But the program is not stopped and go on showing done...
.但是程序并没有停止并继续显示
done...
If you want to wait for it, maybe you can use asyncFunction().then( () => console.log('done...') )
如果你想等待,也许你可以使用
asyncFunction().then( () => console.log('done...') )
Async
keyword used to specify that function will be an instance of AsyncFunction
so it will return Promise
.用于指定该函数的
Async
关键字将是AsyncFunction
一个实例,因此它将返回Promise
。
Await
is used to wait for a promise resolving inside of async function. Await
用于等待在异步函数内部解析的承诺。
According to a mdn - async function can contain an await
expression, that pauses the execution of the async function and waits for the passed promise's resolution, and then resumes the async function's execution and returns the resolved value. 根据 mdn - async 函数可以包含一个
await
表达式,该表达式暂停异步函数的执行并等待传递的承诺的解析,然后恢复异步函数的执行并返回解析的值。
When you await
a function, if that function returns a promise, its return value will be treated as the promise then
value.当您
await
一个函数时,如果该函数返回一个承诺,则其返回值将被视为承诺的then
值。 If the promise will reject, it will be cast to an Error.如果承诺将拒绝,它将被转换为错误。 If the function call returns something ohter than a thenable, well,
await
then just doesn't nothing.如果函数调用返回的不是 thenable 的东西,那么
await
那么什么都不是。
In the other hand, when you declare an async
function, its return value will be returned as a Promise, and any Error thrown from it will be casted to a rejected Promise.另一方面,当你声明一个
async
函数时,它的返回值将作为一个 Promise 返回,并且从它抛出的任何错误都将被转换为一个被拒绝的 Promise。
You can use await
only within an async
declared function.您只能在
async
声明的函数中使用await
。
that's just about async
and await
are, just automatic casting to promises.这只是关于
async
和await
,只是自动转换为承诺。 You don't actually need code using await and async to be really asynchronous (while, well, it's not really useful).您实际上并不需要使用 await 和 async 的代码来实现真正的异步(虽然,它并不是真的有用)。
A quick demonstration:快速演示:
//Will return the string 'Promise' if called through `await`
function getPromise(){
return Promise.resolve('Promise');
}
//Casted to Promise.reject thrught await
function throwError(){
return Promise.reject('error');
}
function get(){
return 'something simple';
}
async function getAsync() {
var response = await getPromise();
return response;
}
//await will cast the rejected Promise to an error
async function getErrorAsync() {
var response = await throwError();
return response;
}
async function simpleGet(){
return get();
}
async function redundantGet(){
return await get();
}
async function catchTheError(){
try{
await throwError();
}
catch(e){
console.log('an error: ' + e );
}
return 'whatever';
}
getAsync().then( console.log ); //Promise
getErrorAsync().catch( console.log ); //error
simpleGet().then( console.log ); //something simple
redundantGet().then( console.log ); //something simple
catchTheError(); //will log 'an error: error'.
So:所以:
waiting is a synchronous function (because it doesn't have async keyword).
等待是一个同步函数(因为它没有 async 关键字)。 So, why can I await a synchronous function?
那么,为什么我可以等待一个同步函数呢?
Because you can.因为你能。 The only thing
await
does is to resolve promise to real values and errors. await
唯一能做的就是解决对真实值和错误的承诺。 You don't actually need the function to return a promise.您实际上并不需要该函数来返回承诺。
Why couldn't done... message be awaited after completing waitingAsync function?
为什么无法完成...完成waitingAsync 函数后等待消息?
async
and await
only makes your code to behave as it would be synchronous iside async
declared functions. async
和await
只会使您的代码表现得像同步 iside async
声明函数一样。 Your last console.log('done')
is outside any async
function, so it will be just logged before that function ends, since it is asynchronous.您的最后一个
console.log('done')
在任何async
函数之外,因此它只会在该函数结束之前被记录,因为它是异步的。
And main question: waitingAsync is an asynchronous function, why is await keyword not required when calling it?
主要问题:waitingAsync 是一个异步函数,为什么调用它时不需要 await 关键字? Just waitingAsync() instead of await waitingAsync().
只是waitingAsync() 而不是await waitingAsync()。
Because async
keyword casts values to promises -and allows to use await
- and nothing more.因为
async
关键字将值转换为 promises - 并允许使用await
- 仅此而已。 In fact, since you can only use await
inside async
functions... you can't expect async
functions to be called through await
, you would need infinite async
functions :-D.实际上,由于您只能在
async
函数中使用await
……您不能期望通过await
调用async
函数,因此您需要无限的async
函数 :-D。
Before diving in, it's good to notice a few things.在潜入之前,最好注意一些事情。
Any reader of the code snippet代码片段的任何读者
let waiting = function () {
return new Promise(resolve => {
console.log('awaiting...');
setTimeout(function () { resolve(); }, 1000);
});
};
let waitingAsync = async function () {
console.log('start...');
await waiting();
console.log('stop...');
};
waitingAsync();
console.log('done...');
may be mislead to believe that the output will be可能会误导认为输出将是
start...
awaiting...
stop...
done...
while – as you have already noted – done...
gets printed before stop...
. while - 正如您已经注意到的 -
done...
在stop...
之前打印。
The reason is that waitingAsync();
原因是
waitingAsync();
is a call to an asynchronous function, while console.log('done...');
是对异步函数的调用,而
console.log('done...');
is just a normal sequential/synchronous statement that gets carried out right away.只是一个正常的顺序/同步语句,可以立即执行。
Question 1 :问题 1 :
waiting
is a synchronous function (because it doesn't haveasync
keyword) [?]waiting
是一个同步函数(因为它没有async
关键字)[?]
Answer :回答:
False.错误的。 The function
waiting
is a synchronous – it returns a Promise .该功能
waiting
是同步的-它返回一个承诺。
Question 2 :问题2 :
Why couldn't
done...
message be awaited after completingwaitingAsync
function?为什么无法
done...
完成waitingAsync
函数后等待消息?
Answer :回答:
Because console.log('done...')
is not asynchronous.因为
console.log('done...')
不是异步的。
(It does not return a Promise.) (它不返回的承诺。)
Question 3 :问题 3 :
And main question:
waitingAsync
is an asynchronous function, why isawait
keyword not required when calling it?主要问题:
waitingAsync
是一个异步函数,为什么调用它时不需要await
关键字?
Answer :回答:
Well, in your example waitingAsync
does not return any value.好吧,在您的示例中
waitingAsync
不返回任何值。 - If it would return a value that you care about, then you would need to await it to get it. - 如果它会返回一个你关心的值,那么你需要等待它来获取它。
( Hello world!
in my Stack Snippet below.) (
Hello world!
在我下面的堆栈片段中。)
Question 4 :问题 4 :
If I can await
waitingAsync()
, [the]done...
message would be printed last [?]如果我可以 await
waitingAsync()
,[the]done...
消息将最后打印 [?]
Answer :回答:
That depends on what exactly you mean.这取决于你的意思。 – See my Stack Snippet below!
– 请参阅下面的堆栈片段! As long as the
Done!
只要
Done!
message is printed within the same callback as the call await waitingAsync()
, the answer is Yes!消息在与调用
await waitingAsync()
相同的回调中打印,答案是肯定的!
But if you put console.log('done...?')
after the call to the asynchronous function that encloses await waitingAsync()
then the answer is No!但是,如果您将
console.log('done...?')
放在对包含await waitingAsync()
的异步函数的调用之后,那么答案是否定的!
When running the snippet below, pay attention to the order of the output!运行下面的代码片段时,请注意输出的顺序!
Also notice how it takes 1400 ms for Promise resolved!
还要注意
Promise resolved!
需要 1400毫秒Promise resolved!
to show up.现身。
function waiting () { return new Promise(resolve => { console.log('awaiting...'); setTimeout(function () { resolve('Hello world!'); console.log('Promise resolved!'); }, 1400); }); } async function waitingAsync () { console.log('start...'); const toBeReturned = await waiting(); console.log('stop...'); return toBeReturned; } (async () => { console.log('Heads up! The next line makes an asynchronous call.'); console.log('Result: ' + await waitingAsync()); // 'Hello world!' console.log('Done! This will be printed LAST! - Agreed?'); })(); console.log('done...?? This is LAST in the CODE. - I awaited \\ "waitingAsync()" above. - So will this be printed at the very end??');
.as-console-wrapper { max-height: 100% !important; top: 0; }
The last asynchronous function is anonymous – without name – and gets called immediately.最后一个异步函数是匿名的——没有名字——并被立即调用。 In fact, this is the only function that gets called directly in the snippet.
事实上,这是在代码片段中直接调用的唯一函数。 The function
waitingAsync
is only called in directly (by the anonymous function), and the function waiting
is also called indirectly (by waitingAsync
).功能
waitingAsync
仅称为直接(通过匿名函数),并且函数waiting
也(通过间接调用waitingAsync
)。
Don't ever put sequential/synchronous code after and outside a call to an asynchronous function!永远不要在调用异步函数之后和之外放置顺序/同步代码!
You will just confuse yourself if you do.如果你这样做,你只会混淆自己。 – And even if you don't get confused, other readers of your code almost certainly will be.
– 即使您没有感到困惑,您的代码的其他读者几乎肯定会感到困惑。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.