在深入了解之前,值得注意几件事情。
任何代码片段的读者。
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...');
只是一个普通的顺序/同步语句,会立即执行。
问题 1:
waiting
是一个 同步 函数(因为它没有 async
关键字)[?]
答案:
错误。 函数 waiting
是 异步 的 - 它返回一个 Promise。
问题2:
在完成waitingAsync
函数后,为什么无法等待done...
消息?
答案:
因为console.log('done...')
不是异步的。
(它不返回Promise。)
问题3::
主要问题是:waitingAsync
是一个异步函数,为什么在调用它时不需要使用await
关键字?
答案:
嗯,在你的例子中,waitingAsync
没有返回任何值。- 如果它返回了你关心的值,那么你需要等待它才能得到它。
(Hello world!
在下面的我的Stack Snippet中。)
问题4:
如果我可以等待waitingAsync()
, 那么done...
信息会最后被打印出来吗?
答案:
这取决于你的具体意思。-请参见下面的我的Stack Snippet!只要Done!
消息在与调用await waitingAsync()
相同的回调函数内被打印,答案是是的。
但是,如果您将console.log('done...?')
放在包含await waitingAsync()
的异步函数调用之后,那么答案是否。
运行下面的代码片段时,请注意输出的顺序!
还要注意需要等待1400ms才会显示“Promise resolved!”的信息。
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());
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)。
一个需要记住的教训
永远不要在异步函数的调用之后和外面放置顺序/同步代码!
如果你这么做,你会把自己搞糊涂。 - 即使你不会感到困惑,你的代码的其他读者几乎肯定会感到困惑。
waitingAsync
函数的返回值会自动转换为Promise
,因为它不能再提供同步结果。因此,现在可以使用await
等待它的执行结果。但这并不是函数能够被等待的唯一方式,否则你将无法编写第一个这样的函数。 - Jesperasync
”并不意味着函数的返回值可以使用“await
”等待。错误! 每个“async
”函数都返回一个Promise
对象。 在这种情况下唯一的注意点是“waiting”函数返回的Promise
无法评估到任何值(void),因为该行代码中存在resolve();
。 - Henke