JS中 Promises 的出现,解决了头疼的回调地狱,但即便如此,引入太多的 then 还是会让代码变的混乱。 ES2017 里新增的 async 和 await 关键字可以很好地来简化 promises 的处理
async 和 await 的特性
- async 是函数声明的关键字
- await 用于 promises 处理过程中
- await 必须用在 async 声明的函数内部
- async 函数返回 promises 对象,不关心函数的返回值是什么
- async/await 和 promises 的底层实现是一样的
async 和 await 介绍
先来一个简单的 async/await 的使用方法:
// 使用 async 定义函数,然后 await 才能使用
async function fetchContent() {
// 之前使用 fetch().then, 现在使用 await
let content = await fetch('/');
let text = await content.text();
// async 函数内,text 是响应值
console.log(text);
// resolve text
return text;
}
// 使用这个 async 函数
let promise = fetchContent().then(...);
先使用 async 声明函数;声明之后,await 才可以用在该函数内部。await 关键字后面跟 promise:fetch API。异步任务执行之后,一直在执行完成才继续下一个任务。最后这个函数处理了返回值并且返回了一个 promises 对象。 代码自上而下,告别回调,异步处理变的更加简单。
转换 Promise 为 await
从使用多个 then 到 await 转换非常简单
fetch('/users.json')
.then(response => response.json())
.then(json => {
console.log(json);
})
.catch(e => { console.log('error!'); })
async function getJson() {
try {
let response = await fetch('/users.json');
let json = await response.json();
console.log(json);
}
catch(e) {
console.log('Error!', e);
}
}
async / await 模式
声明 async 函数有以下方式:
匿名 async 函数
let main = (async function() {
let value = await fetch('/');
})();
async 函数声明
async function main() {
let value = await fetch('/');
};
async 函数赋值
let main = async function() {
let value = await fetch('/');
};
//箭头函数
let main = async () => {
let value = await fetch('/');
};
async 函数作为参数
document.body.addEventListener('click', async function() {
let value = await fetch('/');
});
对象和类方法
// Object
let obj = {
async method() {
let value = await fetch('/');
}
};
// Class
class MyClass {
async myMethod() {
let value = await fetch('/');
}
}
错误处理
传统的 promises 允许使用 catch 回调处理 rejection,当你使用 await,最好使用 try/catch
try {
let x = await myAsyncFunction();
}
catch(e) {
// Error!
}
async / await 和 promises 在底层实现上是一致的,所以可以简单的等待(await)所有的 promises 任务结束
现在大多数浏览器都可以使用 async 和 await,Nodejs 一样可用,async 和 await 可以使可维护性变得更好。