es 7 提供了对 promise 对象的更好的操作,省去了很多丧心病狂的链式异步请求,promise 是回调地狱的福音,而 Async/Await 则是 promise 的天使。
另外,关于 event-loop ,请移步 Event-Loop In Js
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 文档。