(本来想吐槽下去年才熟练使用Promise但是又要用async-await,但是async-await炒鸡好用,默默流泪)
Async/Await与Promise的关系
async-await是promise和generator的语法糖,意在优化promise的写法,简单的说async-await是用来简化pormise写法的,并不是取代关系。
Async/Await基本语法
Async放在function关键字前面,await放在Async关键字的函数里,并且最终返回一个promise对象。如下代码所示:
1
2
3
4
5
6
7
8
9
10
11
12async function asyncAwaitDemo(){
const result = await new Promise((resolve, reject)=>{
setTimeout(()=>{
resolve('test')
},200)
})
return result;
}
asyncAwaitDemo().then((r)=>{
console.log('result:',r);
})
// result: test
需要注意的是await只能放在async关键声明的函数里(这点和yield与*的关系一致)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17// 正常 for 循环
async function demo() {
let arr = [1, 2, 3, 4, 5];
for (let i = 0, len = arr.length; i < len; i ++) {
await arr[i];
}
}
demo();//正常输出
//如果for循环写成下面这样
async function bugDemo() {
let arr = [1, 2, 3, 4, 5];
arr.forEach(item => {
await item;
});
}
bugDemo();// Uncaught SyntaxError: Unexpected identifier
场景示例
这里写一个简单模拟异步api
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
26
27 class Api {
constructor () {
this.user = { id: 1, name: 'test' }
this.friends = [ this.user, this.user, this.user ]
this.photo = 'not a real photo'
}
getUser () {
return new Promise((resolve, reject) => {
setTimeout(() => resolve(this.user), 200)
})
}
getFriends (userId) {
return new Promise((resolve, reject) => {
setTimeout(() => resolve(this.friends.slice()), 200)
})
}
getPhoto (userId) {
return new Promise((resolve, reject) => {
setTimeout(() => resolve(this.photo), 200)
})
}
throwError () {
return new Promise((resolve, reject) => {
setTimeout(() => reject(new Error('Intentional Error')), 200)
})
}
}
需求1:获得用户信息
promise链写法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 function promiseChain () {
const api = new Api()
let user, friends
api.getUser()
.then((returnedUser) => {
user = returnedUser
return api.getFriends(user.id)
})
.then((returnedFriends) => {
friends = returnedFriends
return api.getPhoto(user.id)
})
.then((photo) => {
console.log('promiseChain', { user, friends, photo })
})
}
Async/Await写法
1 | async function asyncAwaitIsYourNewBestFriend () { |
需求2:获得朋友的朋友
promise链写法:这里使用的是迭代循环
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 function promiseLoops () {
const api = new Api()
api.getUser()
.then((user) => {
return api.getFriends(user.id)
})
.then((returnedFriends) => {
const getFriendsOfFriends = (friends) => {
if (friends.length > 0) {
let friend = friends.pop()
return api.getFriends(friend.id)
.then((moreFriends) => {
console.log('promiseLoops', moreFriends)
return getFriendsOfFriends(friends)
})
}
}
return getFriendsOfFriends(returnedFriends)
})
}
Async/Await写法:
1
2
3
4
5
6
7
8
9 async function asyncAwaitLoops () {
const api = new Api()
const user = await api.getUser()
const friends = await api.getFriends(user.id)
for (let friend of friends) {
let moreFriends = await api.getFriends(friend.id)
console.log('asyncAwaitLoops', moreFriends)
}
}
Async/Await写法简化并发
1
2
3
4
5
6
7
8 async function asyncAwaitLoopsParallel () {
const api = new Api()
const user = await api.getUser()
const friends = await api.getFriends(user.id)
const friendPromises = friends.map(friend => api.getFriends(friend.id))
const moreFriends = await Promise.all(friendPromises)
console.log('asyncAwaitLoopsParallel', moreFriends)
}
参考: