规范使用 Promise.then
日常开发中经常碰见需要连续执行多个异步操作,下一个异步操作需要从上一个异步操作返回的结果中获取数据。在这种场景下就适合使用 Promise 的链式调用。
doSomething().then(function(result) {
return doSomethingElse(result);
})
.then(function(newResult) {
return doThirdThing(newResult);
})
.then(function(finalResult) {
console.log('Got the final result: ' + finalResult);
})
.catch(failureCallback);
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
Promise.then 返回一个新的 promise 并带有上个 then 回调函数中返回的结果。
错误的使用方式
const p1 = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve('111')
}, 5000)
})
}
const p2 = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve('222')
}, 1000)
})
}
const p3 = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve('333')
}, 1000)
})
}
// 错误使用嵌套 promise
p1().then(p1Res => {
console.log(p1Res)
p2().then(p2Res => {
console.log(p2Res)
p3().then(p3Res => {
console.log(p3Res)
})
})
})
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
28
29
30
31
32
33
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
28
29
30
31
32
33
以上使用方式中存在几点错误:
- 在一个 then 的回调函数中没有返回,而是嵌套 promise
- 没有发挥 promise 链式调用的优点,与传统回调方式无异,存在回调地狱
- 没有使用 catch 进行错误处理
then 链式调用
正确的使用方式
p1().then(res => {
console.log(res)
return p2()
}).then(res => {
console.log(res)
return p3()
}).then(res => {
console.log(res)
}).catch(err => {
console.log(err)
})
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
时序组合
将多个异步操作按照先后顺序组成数组,用递归方法执行
[p1, p2, p3].reduce((p, f) => p.then(res => {
console.log(res)
return f()
}), Promise.resolve())
.then(res => {console.log(res)})
.catch(err => {console.log(err)})
// 相当于
Promise.resolve()
.then(res => p1())
.then(res => p2())
.then(res => p3())
.catch(err => console.log(err))
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
async/await
使用 async/await 可以更简洁方便地执行时序异步操作
const p1Result = await p1()
const p2Result = await p2()
const p3Result = await p3()
1
2
3
2
3