如何等待异步函数?
How to await an asynchronous function?
我的情况:
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...');
代码中有两处我不明白:
第一个:
await waiting();
waiting
是一个同步函数(因为它没有 async
关键字)。那么,为什么我可以等待一个同步函数?
第二个:
为什么在完成 waitingAsync
功能后不能等待 done...
消息?
还有主要问题:waitingAsync
是一个异步函数,为什么调用时不需要await
关键字?只是 waitingAsync()
而不是 await waitingAsync()
.
如果我可以等待 waitingAsync()
,done...
消息将最后打印。
Async
关键字用于指定该函数将是 AsyncFunction
的实例,因此它将 return Promise
.
Await
用于等待异步函数内部的 promise 解析。
According to a mdn - 异步函数可以包含一个 await
表达式,暂停异步函数的执行并等待传递的承诺的解析,然后恢复异步函数的执行和 returns 解析值。
这不是一个函数,而是一个值,它 return 正在等待 await
语句。
async
和普通函数对于调用者来说没有什么不同。 async
只是 return 一个承诺,在被调用时没有 return 显式地调用它。 waitingAsync()
调用的结果是一个承诺。 waiting()
调用的结果也是一个承诺,所以它不是 'synchronous'。
根据 the spec,promise 和 non-promises 都可以 await
ed。 Non-promises 转换为 Promise.resolve()
的承诺。
console.log('done...')
无法等待,因为它未在 async
函数内部调用。而且它不必 await
ed 因为它不是 return 承诺而是 undefined
。 await
ing 在 async
函数中是可能的。这些 await
用法是一样的,同样没有用,它们所做的只是 1 个刻度延迟:
async function ... {
...
await console.log('done...');
}
async function ... {
...
console.log('done...');
await undefined;
}
async function ... {
...
await Promise.resolve(console.log('done...'));
}
一个async
函数做return一个promise,或者当它使用await
关键字时,它必须等待一个异步函数,一个Promise或另一个async
功能。在您的代码中,waiting()
是一个 return 是 Promise 的函数。那么,await waiting()
是正确的(因为它正在等待异步函数)。
一个async
函数被调用为另一个基本函数被调用。当您希望将函数作为异步函数运行并使用 'await' 关键字时,您可以将函数标记为异步。打印 'done...' 是因为当您调用 asyncFunction()
时,它必须 await
直到 waiting promise
完成。但是程序没有停止,继续显示done...
。如果你想等待,也许你可以使用asyncFunction().then( () => console.log('done...') )
当您 await
函数时,如果该函数 return 是一个承诺,其 return 值将被视为承诺 then
值。如果承诺将被拒绝,它将被转换为一个错误。如果函数调用 return 比 thenable 更重要,那么 await
就什么都不是。
另一方面,当您声明一个 async
函数时,它的 return 值将被 return 编辑为 Promise,并且从中抛出的任何错误都将被转换为一个被拒绝的承诺。
您只能在 async
声明的函数中使用 await
。
差不多 async
和 await
是,只是自动转换为 promise。您实际上并不需要使用 await 和 async 的代码才能真正异步(虽然,它并不是很有用)。
快速演示:
//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'.
所以:
waiting is a synchronous function (because it doesn't have async keyword). So, why can I await a synchronous function?
因为你可以。 await
所做的唯一一件事就是解决对实际值和错误的承诺。您实际上并不需要 return 承诺的功能。
Why couldn't done... message be awaited after completing waitingAsync function?
async
和 await
只会使您的代码表现得像在 async
声明的函数中同步一样。您的最后一个 console.log('done')
在任何 async
函数之外,因此它将在该函数结束之前被记录下来,因为它是异步的。
And main question: waitingAsync is an asynchronous function, why is await keyword not required when calling it? Just waitingAsync() instead of await waitingAsync().
因为 async
关键字将值转换为承诺 - 并允许使用 await
- 仅此而已。事实上,由于您只能在 async
函数中使用 await
...您不能指望通过 await
调用 async
函数,您需要无限的 async
函数:-D.
在开始之前,最好注意一些事情。
任意reader的代码片段
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...');
可能会误以为输出会是
start...
awaiting...
stop...
done...
而 – 正如您已经注意到的 – done...
在 之前 被打印
stop...
.
原因是waitingAsync();
是对异步函数的调用,
而 console.log('done...');
只是一个普通的 sequential/synchronous
立即执行的声明。
问题 1:
waiting
is a synchronous function (because it doesn't have async
keyword) [?]
回答:
False.函数waiting
是a同步 – 它returns
一个承诺.
问题2:
Why couldn't done...
message be awaited after completing waitingAsync
function?
回答:
因为console.log('done...')
是不是异步的。
(它 不是 return Promise。)
问题 3:
And main question: waitingAsync
is an asynchronous function, why is
await
keyword not required when calling it?
回答:
那么,在您的示例中 waitingAsync
没有 return 任何值。 -
如果它 将 return 是您关心的值,那么您需要等待
它得到它。
(Hello world!
在我下面的 Stack Snippet 中。)
问题4:
If I can await waitingAsync()
, [the] done...
message would be printed
last [?]
回答:
这取决于你的意思。 – 请参阅下面我的 Stack Snippet!
只要 Done!
消息在与调用相同的回调中打印
await waitingAsync()
,答案是是!
但是如果你把 console.log('done...?')
放在 之后调用异步
包含 await waitingAsync()
的函数那么答案是 No!
当运行下面的代码片段时,注意输出的顺序!
另请注意 Promise resolved!
需要 1400 ms 才能显示。
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; }
最后一个异步函数是匿名的——没有名字——并且得到
立即打电话。
事实上,这是代码段中唯一 直接 调用的函数。
函数 waitingAsync
仅在 中被直接调用 (由匿名
函数),并且函数 waiting
也被称为 间接
(作者 waitingAsync
)。
外带课
永远不要在 sequential/synchronous 代码 之后和外部 调用
一个异步函数!
如果你这样做,你只会把自己弄糊涂。 – 即使 你 不明白
很困惑,other readers 你的代码几乎肯定会。
我的情况:
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...');
代码中有两处我不明白:
第一个:
await waiting();
waiting
是一个同步函数(因为它没有 async
关键字)。那么,为什么我可以等待一个同步函数?
第二个:
为什么在完成 waitingAsync
功能后不能等待 done...
消息?
还有主要问题:waitingAsync
是一个异步函数,为什么调用时不需要await
关键字?只是 waitingAsync()
而不是 await waitingAsync()
.
如果我可以等待 waitingAsync()
,done...
消息将最后打印。
Async
关键字用于指定该函数将是 AsyncFunction
的实例,因此它将 return Promise
.
Await
用于等待异步函数内部的 promise 解析。
According to a mdn - 异步函数可以包含一个 await
表达式,暂停异步函数的执行并等待传递的承诺的解析,然后恢复异步函数的执行和 returns 解析值。
这不是一个函数,而是一个值,它 return 正在等待 await
语句。
async
和普通函数对于调用者来说没有什么不同。 async
只是 return 一个承诺,在被调用时没有 return 显式地调用它。 waitingAsync()
调用的结果是一个承诺。 waiting()
调用的结果也是一个承诺,所以它不是 'synchronous'。
根据 the spec,promise 和 non-promises 都可以 await
ed。 Non-promises 转换为 Promise.resolve()
的承诺。
console.log('done...')
无法等待,因为它未在 async
函数内部调用。而且它不必 await
ed 因为它不是 return 承诺而是 undefined
。 await
ing 在 async
函数中是可能的。这些 await
用法是一样的,同样没有用,它们所做的只是 1 个刻度延迟:
async function ... {
...
await console.log('done...');
}
async function ... {
...
console.log('done...');
await undefined;
}
async function ... {
...
await Promise.resolve(console.log('done...'));
}
一个async
函数做return一个promise,或者当它使用await
关键字时,它必须等待一个异步函数,一个Promise或另一个async
功能。在您的代码中,waiting()
是一个 return 是 Promise 的函数。那么,await waiting()
是正确的(因为它正在等待异步函数)。
一个async
函数被调用为另一个基本函数被调用。当您希望将函数作为异步函数运行并使用 'await' 关键字时,您可以将函数标记为异步。打印 'done...' 是因为当您调用 asyncFunction()
时,它必须 await
直到 waiting promise
完成。但是程序没有停止,继续显示done...
。如果你想等待,也许你可以使用asyncFunction().then( () => console.log('done...') )
当您 await
函数时,如果该函数 return 是一个承诺,其 return 值将被视为承诺 then
值。如果承诺将被拒绝,它将被转换为一个错误。如果函数调用 return 比 thenable 更重要,那么 await
就什么都不是。
另一方面,当您声明一个 async
函数时,它的 return 值将被 return 编辑为 Promise,并且从中抛出的任何错误都将被转换为一个被拒绝的承诺。
您只能在 async
声明的函数中使用 await
。
差不多 async
和 await
是,只是自动转换为 promise。您实际上并不需要使用 await 和 async 的代码才能真正异步(虽然,它并不是很有用)。
快速演示:
//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'.
所以:
waiting is a synchronous function (because it doesn't have async keyword). So, why can I await a synchronous function?
因为你可以。 await
所做的唯一一件事就是解决对实际值和错误的承诺。您实际上并不需要 return 承诺的功能。
Why couldn't done... message be awaited after completing waitingAsync function?
async
和 await
只会使您的代码表现得像在 async
声明的函数中同步一样。您的最后一个 console.log('done')
在任何 async
函数之外,因此它将在该函数结束之前被记录下来,因为它是异步的。
And main question: waitingAsync is an asynchronous function, why is await keyword not required when calling it? Just waitingAsync() instead of await waitingAsync().
因为 async
关键字将值转换为承诺 - 并允许使用 await
- 仅此而已。事实上,由于您只能在 async
函数中使用 await
...您不能指望通过 await
调用 async
函数,您需要无限的 async
函数:-D.
在开始之前,最好注意一些事情。
任意reader的代码片段
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...');
可能会误以为输出会是
start...
awaiting...
stop...
done...
而 – 正如您已经注意到的 – done...
在 之前 被打印
stop...
.
原因是waitingAsync();
是对异步函数的调用,
而 console.log('done...');
只是一个普通的 sequential/synchronous
立即执行的声明。
问题 1:
waiting
is a synchronous function (because it doesn't haveasync
keyword) [?]
回答:
False.函数waiting
是a同步 – 它returns
一个承诺.
问题2:
Why couldn't
done...
message be awaited after completingwaitingAsync
function?
回答:
因为console.log('done...')
是不是异步的。
(它 不是 return Promise。)
问题 3:
And main question:
waitingAsync
is an asynchronous function, why isawait
keyword not required when calling it?
回答:
那么,在您的示例中 waitingAsync
没有 return 任何值。 -
如果它 将 return 是您关心的值,那么您需要等待
它得到它。
(Hello world!
在我下面的 Stack Snippet 中。)
问题4:
If I can await
waitingAsync()
, [the]done...
message would be printed last [?]
回答:
这取决于你的意思。 – 请参阅下面我的 Stack Snippet!
只要 Done!
消息在与调用相同的回调中打印
await waitingAsync()
,答案是是!
但是如果你把 console.log('done...?')
放在 之后调用异步
包含 await waitingAsync()
的函数那么答案是 No!
当运行下面的代码片段时,注意输出的顺序!
另请注意 Promise resolved!
需要 1400 ms 才能显示。
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; }
最后一个异步函数是匿名的——没有名字——并且得到
立即打电话。
事实上,这是代码段中唯一 直接 调用的函数。
函数 waitingAsync
仅在 中被直接调用 (由匿名
函数),并且函数 waiting
也被称为 间接
(作者 waitingAsync
)。
外带课
永远不要在 sequential/synchronous 代码 之后和外部 调用 一个异步函数!
如果你这样做,你只会把自己弄糊涂。 – 即使 你 不明白 很困惑,other readers 你的代码几乎肯定会。