阮一峰文档

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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
// test01
function strFun(str) {
return new Promise((resolve, reject) => {
if(str.length > 5){
console.log(str);
anotherStr = 'Good!';
return resolve(anotherStr); // 异步操作成功时调用,将异步操作的结果作为参数传递出去
console.log('after resolve')
// resolve只是修改状态,它之后的代码依然会执行,并且由于是同步代码,会在promise的then之前执行
// 推荐在resolve前加return,这样确保resolve之后的代码不执行,避免意外
}
else{
console.log(str + ': This string is too short!');
return reject('Bad!'); // 在异步操作失败时调用,并将异步操作报出的错误,作为参数传递出去。
}
})
}

strFun('Hello World!').then((anotherStr) => {
console.log(anotherStr); // 'Good!'
},(err) => {
console.error(err);
})

strFun('Hi!').then((anotherStr) => {
console.log(anotherStr);
},(err) => {
console.error(err); // 'Bad!'
})

// test02
function timeOut(ms) {
return new Promise((resolve, reject) => {
setTimeout(resolve, ms, 'Done!'); // 第三个参数是向回调函数(第一个参数)中传入的参数
})
}

timeOut(2000).then((value) => {
console.log(value);
})

//test03
const p1 = new Promise((resolve, reject) => {
setTimeout(() => {
return reject(new Error('Fail!'))
}, 3000);
})

const p2 = new Promise((resolve, reject) => {
setTimeout(() => {
return resolve(p1);
// 由于p2的resolve的参数是promise,导致自己的状态无效化
// p2的真实状态由p1决定,而p1在3s后状态变为reject,因此p2的状态在3s后变为reject
}, 1000);
})

p2
.then((msg) => {
console.log(msg);
})
.catch((err) => {
console.error(err); // Fail!
})

// test04

// 很普通的的链式调用
const strArr = ['How are you', 'Fine thank you', 'Nice to meet you'];
strFun(strArr[0]).then(
() => {
strFun(strArr[1]);
},
(err) => {
console.error(err);
}
).then(
() => {
strFun(strArr[2]);
return 114514; // 返回结果会作为参数,传入下一个回调函数
},
(err) => {
console.error(err);
}
).then(
(msg) => {
console.log(msg); // 114514
}
)
// 采用链式的then,可以指定一组按照次序调用的回调函数。这时,前一个回调函数,
// 有可能返回的还是一个Promise对象(即有异步操作),
// 这时后一个回调函数,就会等待该Promise对象的状态发生变化,才会被调用。

// 关于Promise.catch

// Promise 对象的错误具有“冒泡”性质,会一直向后传递,直到被捕获为止。
// 也就是说,错误总是会被下一个catch语句捕获。
// 一般来说,不要在then()方法里面定义 Reject 状态的回调函数,总是使用catch方法。
// 原因:可以捕获前边then方法执行中的错误,也更接近同步的写法

// test05

// finally方法的回调函数不接受任何参数
// finally方法里面的操作,应该是与状态无关的,不依赖于 Promise 的执行结果
strFun('I love u, u love me, mexue ice-cream and tea~').finally(
() => {
console.log('OK'); // OK
}
)
strFun('lmao').finally(
() => {
console.log('OK'); // OK
}
)

尚硅谷视频

Promise.resolve

  • 如果传入的参数为非Promise对象,则返回的结果为成功Promise对象
  • 如果传入的参数为Promise对象,则参数的结果决定了返回的结果
1
2
3
4
5
6
7
8
let p1 = Promise.resolve(111)
let p2 = Promise.resolve(new Promise((res, rej)) => {
// res('OK')
rej('Error')
})
p2.catch(err => {
console.log(err)
})

Promise.reject

和Promise.resolve相比,无论传入什么类型的数据,返回结果都为失败Promise对象,传入什么,失败的内容就是什么

Promise.all

传入包含n个Promise的数组,返回一个新的Promise,只有所有的Promise都成功才成功,否则失败

若成功,将成功值保存在一个数组中;若失败,只将第一个失败的值保存

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
let p1 = new Promise((res, rej) => {
res('OK')
})
let p2 = Promise.resolve('Success')
let p3 = Promise.resolve('Oh Yeah')
// let p3 = Promise.reject('Oh Yeah')

const result = Promise.all([p1, p2, p3])

result.then(value => {
console.log(value) //  ["OK", "Success", "Oh Yeah"]
})

result.catch(err => {
console.log(err)
})

Promise.race

和all类似,不同之处:第一个执行完毕的Promise的结果决定了Promise.race返回值的结果