JavaScript|async/await

基本概念

Promise等价

async 关键字声明的函数本质上就是隐式返回了一个Promise,并将结果值作为 resolve 的内容

1
2
3
4
async function asyncFunction() {
return 1;
}

等价于

1
2
3
function newPromiseEquivalent() {
return Promise.resolve(1);
}

Future.get

在 async 声明的函数中定义 await,等价于我们针对Promise的异步操作声明后,同步阻塞调用了一次get(类似Java语言中Future的get())

1
2
3
4
5
6
7
8
9
10
async function sleepAndWaitOneSec() {
let pro = new Promise((resolve) => {
setTimeout(() => {
resolve('sleep done');
}, 1000);
});
let res = await pro; //同步阻塞
alert(res);
}

我们可以简单理解为,await 是获取Promise结果的一个等同于then 处理程序的一个简洁形式

例如原先展示图片案例的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
function showImage() {
fetch('./foo.json')
.then((response) => response.json())
.then((user) => fetch(`https://avatars.githubusercontent.com/${user.name}`))
.then((response) => response.json())
.then(
(githubUser) =>
new Promise((resolve) => {
let img = document.createElement('img');
img.src = githubUser.avatar_url;
img.className = 'promise-avatar-example';
document.body.append(img);
setTimeout(() => {
img.remove();
resolve(githubUser);
}, 3000);
}),
);
}

可以重构为

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
async function showImageAsync() {
//当远程服务器返回 header(是在全部响应加载完成前)时,该 promise 使用一个 response 对象来进行 resolve
let response = await fetch("./foo.json");
//当全部文字内容从远程服务器下载完成后,它会返回一个 promise
let user = await response.json();

let resp = await fetch(`http://avatars.githubusercontent.com/${user.name}`);
let githubUser = await resp.json();

let img = document.createElement('img');
img.src = githubUser.avatar_url;
img.className = 'promise-avatar-example';
document.body.append(img);

//同步阻塞
await new Promise((resolve) => {
setTimeout(() => {
resolve()
}, 3000)
});
//时间到了之后删除
img.remove();
//异步函数应当始终返回Promise
return githubUser;
}

异常处理

如果 await 的 promise 出现了异常,我们可以使用 catch 块来进行捕获

1
2
3
4
5
6
7
8
9
async function errorPromise() {
try {
let res = await fetch('no-such-url');
let data = await res.json();
} catch (err) {
alert(err);
}
}

需要注意区分这种的写法

1
Promise.reject(new Error('Fatal error')).catch(alert)

写法不同但是效果相同,一般我们在使用async/await的时候都基本不会再去使用.then()或者是.catch(),一般都是直接变量接收,然后配合catch块来进行使用

总结

有了 async/await 之后,我们就几乎不需要使用 promise.then/catch,但是不要忘了它们是基于 promise 的,因为有些时候(例如在最外层作用域)我们不得不使用这些方法


JavaScript|async/await
http://example.com/2025/02/25/JavaScript-async-await/
作者
Noctis64
发布于
2025年2月25日
许可协议