es 7 提供了对 promise 对象的更好的操作,省去了很多丧心病狂的链式异步请求,promise 是回调地狱的福音,而 Async/Await 则是 promise 的天使。
Await
await 关键字修饰的东西只能用在 async 修饰的函数中,这就意味着,await 的出现一定会有 async 的身影。因此,await 不能工作在顶级作用域中。
await 关键字往往修饰的是 promise 对象。
// 只能在async函数内部使用
let value = await promise
关键词 await
可以让 JavaScript 进行等待,直到一个 promise 执行并返回它的结果,JavaScript才会继续往下执行。
Async
async 用来修饰函数,可以用来修饰内部没有 await 的函数。当然,如果这个函数有 return 语句,js 会自动将返回值包装成 resolved 值(promise 对象)。例如:
async function f() {
return 1
}
f().then(res => console.log(res)) // 1
等价于:
async function f() {
return Promise.resolve(1)
}
f().then(res => console.log(res)) // 1
示例部分:
1.promise 在 1s 之后 resolve 的例子:
async function f() {
let promise = new Promise((resolve, reject) => {
setTimeout(() => resolve('done!'), 1000)
})
let result = await promise // 直到promise返回一个resolve值(*)
console.log(result) // 1s 后打印 字符串 'done!'
}
f()
2.多个 await 完成链式操作:
async function showAvatar() {
// read our JSON
let response = await fetch('/article/promise-chaining/user.json')
let user = await response.json()
// read github user
let githubResponse = await fetch(`https://api.github.com/users/${user.name}`)
let githubUser = await githubResponse.json()
// 展示头像
let img = document.createElement('img')
img.src = githubUser.avatar_url
img.className = 'promise-avatar-example'
documenmt.body.append(img)
// 等待3s
await new Promise((resolve, reject) => {
setTimeout(resolve, 3000)
})
img.remove()
return githubUser
}
showAvatar()
promise 链式操作版:
function loadJson(url) {
return fetch(url)
.then(response => response.json());
}
function loadGithubUser(name) {
return fetch(`https://api.github.com/users/${name}`)
.then(response => response.json());
}
function showAvatar(githubUser) {
return new Promise(function(resolve, reject) {
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);
});
}
// Use them:
loadJson('/article/promise-chaining/user.json')
.then(user => loadGithubUser(user.name))
.then(showAvatar)
.then(githubUser => alert(`Finished showing ${githubUser.name}`));
// ...
错误处理:
promise 对象可不仅仅会具有 resolved 值,还会产生 rejected 值,当遇到 rejected 的时候,我们可以用两种方式来处理。
- try - catch 捕获:
try { let response = await fetch('/no-user-here') let user = await response.json() } catch(err) { // 在fetch和response.json中都能捕获错误 alert(err) }
- 链式 catch 捕获:
async function f() { let response = await new Promise((resolve, reject) => { setTimeout(() => { reject('123') }, 1000) }) } // f()变成了一个rejected的promise f().catch(err => console.log(err)) // 1s 后打印 ‘123’
更多复杂用法详见 es7 文档。