基本概念
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() { let response = await fetch("./foo.json"); 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(); 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 的,因为有些时候(例如在最外层作用域)我们不得不使用这些方法