这个错误的原因,是我们在一个普通函数里调用了async函数,因为async 函数是异步函数,它返回一个 Promis,await必须与async一同出现。所以这里普通函数无法调用它。
async和await只是使函数调用看起来像同步而已,比如下面的示例:
<html>
<head>
<title>My Website</title>
</head>
<body>
<script type="text/javascript">
// 定义一个返回 Promise 的异步函数
function fetchData() {
return new Promise((resolve) => {
setTimeout(() => {
resolve("数据获取成功!");
}, 5000);
});
}
// 使用 async 和 await
async function AsyncFetchData() {
console.log("开始获取数据...");
try {
// 等待 fetchData 函数返回的 Promise
const result = await fetchData();
// 输出fetchData 函数的PromiseResult
console.log("fetchData()的结果--->");
console.log(result);
} catch (error) {
console.error("获取数据失败:", error);
}
}
// 程序调用async函数
function main() {
console.log("程序开始执行");
AsyncFetchData();
console.log("程序执行完毕");
}
main();
</script>
</body>
</html>
执行结果:
等待几秒钟后:
我们把AsyncFetchData()方法的代码拷贝进main(),从执行结果,我们可以看出其执行顺序是将AsyncFetchData()方法分隔成了两部分运行 (以await那一行代码为分割线),
function main() {
console.log("程序开始执行"); // main()
//AsyncFetchData()上半部分 begin
{async function AsyncFetchData() {
console.log("开始获取数据...");
try {
// 等待 fetchData 函数返回的 Promise
const result = await fetchData();}
//AsyncFetchData()上半部分 end
console.log("程序执行完毕"); // main()
//AsyncFetchData() 下半部分 begin
{
// 输出fetchData 函数的PromiseResult
console.log("fetchData()的结果--->");
console.log(result);
} catch (error) {
console.error("获取数据失败:", error);
}
}
//AsyncFetchData() 下半部分 end
}
main()执行到AsyncFetchData()方法的await时,就会直接进行main()的其他代码,直到Promise返回结果后才会执行AsyncFetchData()方法的await后的代码。
如果我们非要main()内部是同步运行,我们使用await 调用AsyncFetchData()方法来等待其执行完毕,会遇到 仅允许在异步函数和模块顶级使用 "await" 错误,因为main是普通函数
必须把main()也定义为异步函数:
// 程序调用async函数
async function main() {
console.log("程序开始执行");
await AsyncFetchData();
console.log("程序执行完毕");
}
main();
结果显示,是同步运行:
但是因为main()也是异步函数,如果它被其他普通函数调用,main()函数也会被从await分成两部分运行。
所以async和await只是使函数调用看起来像同步而已
另外,假如异步函数有返回值的话,返回的仍然是Promise对象,可以使用.then()做回调:
async function AsyncFetchData() {
console.log("开始获取数据...");
try {
// 等待 fetchData 函数返回的 Promise
const result = await fetchData();
// 输出fetchData 函数的PromiseResult
console.log("fetchData()的结果--->");
console.log(result);
return result;//返回Promise
} catch (error) {
console.error("获取数据失败:", error);
}
}
// 程序调用async函数
function main() {
console.log("程序开始执行");
AsyncFetchData().then((re)=>{
console.log("AsyncFetchData的返回--->");
console.log(re);
});
console.log("程序执行完毕");
}
main();
结果如下,注意仍然是异步执行。
延申:
如果有多个异步函数,它们的执行时间不一样,我们如何保证能按照顺序获得结果而不乱套呢。答案是使用Promise.all():
const promise1 = new Promise((resolve) => {
setTimeout(() => resolve("结果1"), 3000); // 3秒后 resolved
});
const promise2 = new Promise((resolve, reject) => {
setTimeout(() => resolve("结果2"), 5000); // 5秒后 resolved
});
const promise3 = new Promise((resolve, reject) => {
setTimeout(() => resolve("结果3"), 2000); // 2秒后 resolved
});
// 使用 Promise.all
Promise.all([promise1, promise2, promise3])
.then((results) => {
console.log(results);
})
.catch((error) => {
console.error("捕获到错误:", error);
});
三个异步函数的执行时间是混乱的,我们使用Promise.all()可以按照顺序得到结果: