七、Promise对象的深入学习
Lyk 2022/8/8 ES6PromisePromise类
# 1、异步任务的处理
- 在ES6出来之后,有很多关于Promise的讲解、文章,也有很多经典的书籍讲解Promise
- 虽然等你学会Promise之后,会觉得Promise不过如此;
- 但是在初次接触的时候都会觉得这个东西不好理解;
- 那么这里我从一个实际的例子来作为切入点:
- 我们调用一个函数,这个函数中发送网络请求(我们可以用定时器来模拟);
- 如果发送网络请求成功了,那么告知调用者发送成功,并且将相关数据返回过去;
- 如果发送网络请求失败了,那么告知调用者发送失败,并且告知错误信息;
function requestData(url,successCallback,failureCallback) {
setTimeout(()=>{
if(url === 'http://test.org'){
//发送请求成功
const res = ['nba','cba','ncaa']//请求成功拿到的数据
successCallback(res)
}else {
//发送请求失败
failureCallback('请求url错误')
}
},2000)
}
function success(res) {
console.log('请求成功!拿到的数据为:',res)
}
function failure(err) {
console.log('请求失败,失败原因为:',err)
}
requestData('http://test1.org',success,failure)//请求失败,失败原因为: 请求url错误
requestData('http://test.org',success,failure)//请求成功!拿到的数据为: [ 'nba', 'cba', 'ncaa' ]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 2、什么是Promise呢?
- 在上面的解决方案中,我们确确实实可以解决请求函数得到结果之后,获取到对应的回调,但是它存在两个主要的问题:
- 第一,我们需要自己来设计回调函数、回调函数的名称、回调函数的使用等;
- 第二,对于不同的人、不同的框架设计出来的方案是不同的,那么我们必须耐心去看别人的源码或者文档,以便可以理解它这个函数到底怎么用;
- 我们来看一下Promise的API是怎么样的:
- Promise是一个类,可以翻译成 承诺、许诺 、期约;
- 当我们需要的时候,给予调用者一个承诺:待会儿我会给你回调数据时,就可以创建一个Promise的实例对象;
- 在通过new创建Promise实例对象时,我们需要传入一个回调函数,我们称之为executo
- executo这个回调函数会被立即执行,并且给传入另外两个回调函数resolve、reject;
- 当我们调用resolve回调函数时,会执行Promise实例对象的then方法传入的回调函数;
- 当我们调用reject回调函数时,会执行Promise实例对象的catch方法传入的回调函数;
//1.当我们调用resolve回调函数时
new Promise((resolve, reject) => {
resolve(['nba', 'cba', 'ncaa'])//会执行Promise实例对象的then方法传入的回调函数;
}).then(res => {
console.log(res)//[ 'nba', 'cba', 'ncaa' ]
}).catch(err => {
console.log(err)
})
//2.当我们调用reject回调函数时
new Promise((resolve, reject) => {
reject('请求失败')//会执行Promise实例对象的catch方法传入的回调函数;
}).then(res => {
console.log(res)
}).catch(err => {
console.log(err)//请求失败
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 3、Promise的代码结构
- 我们来看一下new一个Promise的代码结构:
function request(url) {
return new Promise((resolve, reject) => {
if (url === 'http://test.org') {
//执行了resolve时,处于该状态,Promise已经被兑现
resolve(['nba', 'cba', 'ncaa'])
} else {
//已拒绝(rejected): 意味着操作失败;
reject('请求失败')
}
})
}
//这里request()调用拿到的返回值是一个Promise实例对象
request('http://test.org').then(res => {
console.log(res)//[ 'nba', 'cba', 'ncaa' ]
}).catch(err => {
console.log(err)
})
// request('http://test1.org').then(res => {
// console.log(res)
// }).catch(err => {
// console.log(err)//请求失败
// })
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
- 上面Promise使用过程,我们可以将它划分成三个状态:
- 待定(pending): 初始状态,既没有被兑现,也没有被拒绝;
- 当执行executor中的代码时,处于该状态;
- 已兑现(fulfilled): 意味着操作成功完成;
- 执行了resolve时,处于该状态,Promise已经被兑现;
- 那么:该Promise实例对象的then方法中的回调函数会执行
- 已拒绝(rejected): 意味着操作失败;
- 执行了reject时,处于该状态,Promise已经被拒绝;
- 那么:该Promise实例对象的catch方法中的回调函数会执行
- 待定(pending): 初始状态,既没有被兑现,也没有被拒绝;
# 4、Promise重构请求
- 那么有了Promise,我们就可以将之前 模拟发送网络请求的 代码进行重构了:
function request(url) {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (url === 'http://test.org') {
resolve(['nba', 'cba', 'ncaa'])
} else {
reject('请求失败')
}
}, 2000)
})
}
request('http://test.org').then(res => {
console.log(res)//[ 'nba', 'cba', 'ncaa' ]
}).catch(err => {
console.log(err)
})
// request('http://test1.org').then(res => {
// console.log(res)
// }).catch(err => {
// console.log(err)//请求失败
// })
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 5、Executor回调函数 - (new Promise(Executor))
- Executor是在创建Promise实例对象时需要传入的一个回调函数,这个回调函数会被立即执行,并且传入两个参数:
new Promise((resolve,reject) => {
console.log('executor回调函数内部代码会被立即执行')
})
1
2
3
2
3
- 通常我们会在Executor中确定我们的Promise状态:
- 通过resolve,可以兑现(fulfilled)Promise的状态,我们也可以称之为已决议(resolved);
- 通过reject,可以拒绝(reject)Promise的状态;
- 这里需要注意:一旦状态被确定下来,Promise的状态会被 锁死,该Promise的状态是不可更改的
- 在我们调用resolve的时候,如果resolve传入的值本身不是
一个Promise或一个有实现then方法的对象
,那么会将该Promise的状态变成 兑现(fulfilled);【如果resolve传入的值是其他值的情况,具体看下面:6、resolve回调函数传入不同值的区别
】 - 在之后我们去调用reject时,已经不会有任何的响应了(并不是这行代码不会执行,而是无法改变Promise状态);
- 在我们调用resolve的时候,如果resolve传入的值本身不是
new Promise((resolve,reject) => {
resolve('已兑现')//一旦状态被确定下来,Promise的状态会被 锁死,该Promise的状态是不可更改的
reject('已拒绝')//状态已经确定了,状态被锁死,无法更改
resolve('兑现了')//状态已经确定了,状态被锁死,无法更改
}).then(res => {
console.log(res)//已兑现
}).catch(err => {
console.log(err)
})
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
# 6、resolve回调函数传入不同值的区别
- 情况一:如果resolve传入一个普通的值或者对象,那么这个值会作为then回调的参数;
- 情况二:如果resolve中传入的是另外一个Promise,那么这个新Promise会决定原Promise的状态:
- 情况三:如果resolve中传入的是一个对象,并且这个对象有实现then方法,那么会执行该then方法,并且根据then方法的结果来决定Promise的状态:
//1.情况一:如果resolve传入一个普通的值或者对象,那么这个值会作为then回调的参数;
new Promise((resolve, reject) => {
// resolve(111)
// resolve('aadf')
// resolve(false)
// resolve({name:'kobe'})
resolve(['aaa', 'bbb'])
}).then(res => {
console.log(res)//[ 'aaa', 'bbb' ]
}).catch(err => {
console.log(err)
})
//2.情况二:如果resolve中传入的是另外一个Promise,那么这个新Promise会决定原Promise的状态:
//2.1 resolve中传入的是另外一个Promise实例对象;且有决定状态
new Promise((resolve, reject) => {
resolve(new Promise((resolve, reject) => {
resolve('已兑现')
}))
reject('已经拒绝')//状态已经确定了为:resolve('已兑现'),状态被锁死,无法更改
}).then(res => {
console.log(res)//已兑现
}).catch(err => {
console.log(err)
})
//2.2 resolve中传入的是另外一个Promise实例对象;且没有决定状态
new Promise((resolve, reject) => {
resolve(new Promise((resolve, reject) => {//如果新传入的Promise没有决定状态,则原Promise的状态为:待定
console.log('没有决定状态,则原Promise的状态为:待定')
}))
reject('已经拒绝')//状态已经确定了为:resolve('已兑现'),状态被锁死,无法更改
}).then(res => {
console.log(res)
}).catch(err => {
console.log(err)
})
//2.3 resolve中传入的是另外一个Promise
new Promise((resolve, reject) => {
resolve(Promise.resolve('已经兑现')) //Promise.resolve('已经兑现')该方法是Promise类方法,后面会学习
reject('已经拒绝')//状态已经确定了为:resolve('已兑现'),状态被锁死,无法更改
}).then(res => {
console.log(res)//已经兑现
}).catch(err => {
console.log(err)
})
// 3.情况三:如果resolve中传入的是一个对象,并且这个对象有实现then方法,那么会执行该then方法,并根据then方法来决定Promise的状态:
new Promise((resolve,reject) => {
resolve({
then(resolve,reject) {//如果该then方法中没有决定状态,那么Promise的状态将为:待定 (与上面案例2.3同理)
console.log('传入的对象的then方法执行了')
reject('拒绝')
}
})
reject('已经拒绝')////状态已经确定了为:reject('拒绝'),状态被锁死,无法更改
}).then(res => {
console.log(res)
}).catch(err => {
console.log(err)//拒绝
})
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
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
# 7、then实例方法 – 接受两个参数
- then方法是Promise对象上的一个方法(实例方法):
- 它其实是放在Promise的原型上的 Promise.prototype.then
- then方法接收两个参数:
- fulfilled的回调函数:当状态变成fulfilled(已兑现)时会回调的函数;
- reject的回调函数:当状态变成reject时会回调的函数;
- 所以还有如下写法:
// 1.then方法接收两个参数 Promise.prototype.then(fulfilled,reject)
new Promise((resolve, reject) => {
//resolve("已经兑现状态")
reject('拒绝状态')
}).then(res => {
console.log(res)
}, err => {
console.log(err)
})
// 2.上面写法等价于下面的写法 (个人更推荐下面这种写法)
new Promise((resolve, reject) => {
//resolve("已经兑现状态")
reject('拒绝状态')
}).then(res => {
console.log(res)
}).catch(err => {
console.log(err)
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 8、then实例方法 – 多次调用
- 一个Promise的then方法是可以被多次调用的:
- 每次调用我们都可以传入对应的fulfilled回调;
- 当Promise的状态变成fulfilled的时候,这些回调函数都会被执行;
const promise = new Promise((resolve,reject) => {
resolve('已经兑现状态')
})
promise.then(res => {
console.log(res)//已经兑现状态
})
promise.then(res => {
console.log(res)//已经兑现状态
})
promise.then(res => {
console.log(res)//已经兑现状态
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 9、then实例方法 – 返回值
- then方法本身是有返回值的,它的返回值是一个Promise,所以我们可以进行如下的链式调用:
- 但是then方法返回的Promise到底处于什么样的状态呢?
new Promise((resolve,reject) => {
resolve('兑现状态')
}).then(res => {
console.log(res)//兑现状态
}).then(res => {
console.log(res)//undefined
}).then(res => {
console.log(res)//undefined
})
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
# Promise有三种状态,那么这个Promise处于什么状态呢?
pending(待定)状态:当then方法中的回调函数本身在执行的时候,那么它处于pending(待定)状态;
fulfilled(兑现)状态:当then方法中的回调函数返回一个结果时,那么它处于fulfilled(兑现)状态,并且会将结果作为resolve的参数;
const p = new Promise((resolve,reject)=>{ resolve('kobe') }) const p1 = p.then(res => { const xxx = '我是p.then中回调函数的返回值' console.log(res)//kobe return xxx // 即:p.then()方法执行后 新返回的Promise中 会执行 resolve(xxx) ---->【重点】 }) console.log(p1)//Promise { <pending> } p1.then(res=>{ console.log('我拿到了:',res)//我拿到了: 我是p.then中回调函数的返回值 }) /**理解:上面:p.then(res=> {return xxx})发生了什么操作;从而理解p1.then的回调函数中为什么可以拿到 p.then中回调函数的返回值 * p.then(res=>{return xxx})方法的返回值是一个新的Promise; * 如果p.then(res=>{return xxx})方法中的回调函数有返回一个结果:xxx,那么这个新的Promise将处于fulfilled(兑现)状态; * 这时会将这个返回的结果作为新的Promise中resolve的参数;并会直接调用resolve(xxx) * 这样我们在下一个链式调用的p1.then(res=>{})方法的回调函数中,就可以拿到上一个p.then(res=>{return xxx})方法中回调函数的返回值:xxx了; * 将上面方便我们理解的代码,还原成如下代码;即可理解啦 */ new Promise((resolve,reject)=>{ resolve('kobe') }).then(res => { const xxx = '我是p.then中回调函数的返回值' console.log(res)//kobe return xxx }).then(res=>{ console.log('我拿到了:',res)//我拿到了: 我是p.then中回调函数的返回值 })
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- 情况一:then方法中的回调函数返回一个普通的值;
- 情况二:then方法中的回调函数返回一个Promise;
- 跟上面new Promise(executor)创建实例对象时,Executor回调函数内部调用resolve回调函数时,传入的值是
一个Promise
一样理解
- 跟上面new Promise(executor)创建实例对象时,Executor回调函数内部调用resolve回调函数时,传入的值是
- 情况三:then方法中的回调函数返回一个thenable值;
- 跟上面new Promise(executor)创建实例对象时,Executor回调函数内部调用resolve回调函数时,传入的值是
一个实现了then方法的对象
一样理解
- 跟上面new Promise(executor)创建实例对象时,Executor回调函数内部调用resolve回调函数时,传入的值是
// 1- 情况一:返回一个普通的值;
new Promise((resolve,reject) => {
resolve('兑现状态')
}).then(res => {//
console.log(res)//兑现状态
return 'nba'
}).then(res => {
console.log(res)//nba
return 999
}).then(res => {
console.log(res)//999
return {name:'kobe'}
}).then(res => {
console.log(res)//{name:'kobe'}
})
// 2- 情况二:返回一个Promise;
new Promise((resolve,reject) => {
resolve(['nba','cba'])
}).then(res => {
console.log(res)//['nba','cba']
// return Promise.resolve('ncaa')
return new Promise((resolve,reject) => {resolve('ncaa')})
}).then(res => {
console.log(res)//ncaa
})
// 3- 情况三:返回一个thenable值;
new Promise((resolve, reject) => {
resolve(['nba', 'cba'])
}).then(res => {
console.log(res)//['nba','cba']
// return Promise.resolve('ncaa')
return {
then(resolve, reject) {
resolve('ncaa')
}
}
}).then(res => {
console.log(res)//ncaa
})
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
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
- rejected(拒绝)状态:当then方法抛出一个异常时,那么它处于rejected(拒绝)状态;
new Promise((resolve, reject) => {
resolve(['kobe', 'james', 'curry'])
}).then(res => {
throw new Error('报错了!')
}).then(res => {
console.log('-------')//没有执行 直接找最近的catch方法
console.log(res)//没有执行 直接找最近的catch方法
}).catch(err => {
console.log('+++++++')//++++++
console.log(err)//Error: 报错了!
})
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
# 10、catch实例方法 – 多次调用
- catch方法也是Promise对象上的一个方法(实例方法):
- 它也是放在Promise的原型上的 Promise.prototype.catch
- 一个Promise的catch方法是可以被多次调用的:
- 每次调用我们都可以传入对应的reject回调;
- 当Promise的状态变成reject的时候,这些回调函数都会被执行;
const promise = new Promise((resolve,reject) => {
reject('已经拒绝状态')
})
promise.catch(err => {
console.log(err)//已经拒绝状态
})
promise.catch(err => {
console.log(err)//已经拒绝状态
})
promise.catch(err => {
console.log(err)//已经拒绝状态
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 11、catch实例方法 – 返回值
- 事实上catch方法也是会返回一个Promise对象的,所以catch方法后面我们可以继续调用then方法或者catch方法:
- 下面的代码,后续是catch中的err2打印,还是then中的res打印呢?
- 答案是res打印,这是因为catch传入的回调在执行完后,默认状态依然会是fulfilled的;所以会去执行返回的新Promise对象的then方法
const promise = new Promise((resolve,reject) => {
reject('error')
})
promise.catch(err => {//注意:catch传入的回调在执行完后,默认状态依然会是fulfilled(兑现状态)的; --> 继续执行then方法
console.log('err1',err)//err1 error
}).catch(err => {
console.log('err2',err)//不会执行
}).then(res => {
console.log('res',res)//res undefined
})
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
- 那么如果我们希望后续继续执行catch,那么需要抛出一个异常:
const promise = new Promise((resolve,reject) => {
reject('error')
})
promise.catch(err => {
console.log('err1',err)//err1 error
throw new Error('message error')//抛出一个异常,变成了 rejected状态(拒绝状态) -> 继续执行catch方法
}).catch(err => {//这里没有抛出异常,默认为fulfilled(兑现状态) -> 继续执行then方法
console.log('err2',err)//err2 Error: message error
return 'res'
}).then(res => {
console.log('res',res)//res res
})
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
# 12、finally实例方法
- finally是在ES9(ES2018)中新增的一个特性:表示无论Promise对象无论变成fulfilled还是rejected状态,最终都会被执行的代码。(注:待定状态不会执行)
- finally方法中的回调函数是不接收参数的,因为无论前面是fulfilled状态,还是rejected状态,finally方法都会执行。
new Promise((resolve,reject) => {
// resolve('success')
reject('error')
}).then(res=> {
console.log(res)
}).catch(err => {
console.log(err)
}).finally(()=>{
console.log('只要不是待定状态,我都会执行')
})
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
# 13、resolve类方法
- 前面我们学习的then、catch、finally方法都属于Promise的实例方法,都是存放在Promise的prototype上的。
- 下面我们再来学习一下Promise的类方法。
- 有时候我们已经有一个现成的内容了,希望将其转成Promise来使用,这个时候我们可以使用 Promise.resolve 方法来完成。
- Promise.resolve的用法相当于new Promise,并且执行resolve操作:
- resolve参数的形态:
- 情况一:参数是一个普通的值或者对象
- 情况二:参数本身是Promise
- 情况三:参数是一个thenable
// - 情况一:参数是一个普通的值或者对象
Promise.resolve('bbb').then(res => {
console.log(res)//bbb
}).catch(err => {
console.log(err)
})
// - 情况二:参数本身是Promise
Promise.resolve(new Promise(resolve => {resolve('ccc')})).then(res => {
console.log(res)//ccc
}).catch(err => {
console.log(err)
})
Promise.resolve(Promise.reject('error info')).then(res => {
console.log(res)
}).catch(err => {
console.log(err)//error info
})
// - 情况三:参数是一个thenable
Promise.resolve({then(resolve){resolve('ddd')}}).then(res => {
console.log(res)//ddd
}).catch(err => {
console.log(err)
})
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
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
# 14、reject类方法
- reject方法类似于resolve方法,只是会将Promise对象的状态设置为rejected状态。
- Promise.reject的用法相当于new Promise,只是会调用reject:
- Promise.reject传入的参数无论是什么形态,都会直接作为rejected状态的参数传递到catch的。
Promise.reject('message error').then(res => {
console.log(res)
}).catch(err => {
console.log(err)//message error
})
1
2
3
4
5
2
3
4
5
# 15、all类方法
- 另外一个类方法是Promise.all:
- 它的作用是将多个Promise包裹在一起形成一个新的Promise;
- 新的Promise状态由包裹的所有Promise共同决定:
- 当所有的Promise状态变成fulfilled状态时,新的Promise状态为fulfilled,并且会将所有Promise的返回值组成一个数组;
- 当有一个Promise状态为reject时,新的Promise状态为reject,并且会将第一个reject的返回值作为参数;
//1. 当所有的Promise状态变成fulfilled状态时,新的Promise状态为fulfilled,并且会将所有Promise的返回值组成一个数组;
const p1 = new Promise((resolve,reject) => {
// reject('message error p1')
resolve('p1 info')
})
const p2 = new Promise((resolve,reject) => {
// reject('message error p2')
resolve('p2 info')
})
const p3 = new Promise((resolve,reject) => {
// reject('message error1 p3')
resolve('p3 info')
})
Promise.all([p1,p2,p3]).then(res => {
console.log(res)//[ 'p1 info', 'p2 info', 'p3 info' ]
}).catch(err => {
console.log(err)
})
//2. 当有一个Promise状态为reject时,新的Promise状态为reject,并且会将第一个reject的返回值作为参数;
const p4 = new Promise((resolve,reject) => {
// reject('message error p4')
resolve('p4 info')
})
const p5 = new Promise((resolve,reject) => {
reject('message error p5')
// resolve('p5 info')
})
const p6 = new Promise((resolve,reject) => {
reject('message error1 p6')
// resolve('p6 info')
})
Promise.all([p4,p5,p6]).then(res => {
console.log(res)
}).catch(err => {
console.log(err)//message error p5
})
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
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
# 16、allSettled类方法
- all方法有一个缺陷:当有其中一个Promise变成rejected状态时,新Promise就会立即变成对应的rejected状态。
- 那么对于resolved的,以及依然处于pending状态的Promise,我们是获取不到对应的结果的;
- 在ES11(ES2020)中,添加了新的API Promise.allSettled:
- 该方法会在所有的Promise都有结果(settled),无论是fulfilled,还是rejected时,才会有最终的状态;
- 并且这个Promise的结果一定是fulfilled的;
- 我们来看一下打印的结果:
- allSettled的结果是一个数组,数组中存放着每一个Promise的结果,并且是对应一个对象的;
- 这个对象中包含status状态,以及对应的value值;
const p1 = new Promise((resolve,reject) => {
// reject('message error p1')
resolve('p1 info')
})
const p2 = new Promise((resolve,reject) => {
reject('message error p2')
// resolve('p2 info')
})
const p3 = new Promise((resolve,reject) => {
// reject('message error1 p3')
resolve('p3 info')
})
Promise.allSettled([p1,p2,p3]).then(res => {
console.log(res)
/* 打印结果:
[
{ status: 'fulfilled', value: 'p1 info' },
{ status: 'rejected', reason: 'message error p2' },
{ status: 'fulfilled', value: 'p3 info' }
]
*/
}).catch(err => {
console.log(err)
})
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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# 17、race类方法
- 如果有一个Promise有了结果,我们就希望决定最终新Promise的状态,那么可以使用race方法:
- race是竞技、竞赛的意思,表示多个Promise相互竞争,谁先有结果,那么就使用谁的结果;
//如下代码。由于没有模拟网络请求,所以按照顺序执行。p1的Promise先执行即先有结果,那就使用p1的结果
const p1 = new Promise((resolve,reject) => {
reject('message error p1')
// resolve('p1 info')
})
const p2 = new Promise((resolve,reject) => {
// reject('message error p2')
resolve('p2 info')
})
const p3 = new Promise((resolve,reject) => {
// reject('message error1 p3')
resolve('p3 info')
})
Promise.race([p1,p2,p3]).then(res => {
console.log(res)
}).catch(err => {
console.log(err)//message error p1
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 18、any类方法
- any方法是ES12中新增的方法,和race方法是类似的:
- any方法会等到一个fulfilled状态,才会决定新Promise的状态;
- 如果所有的Promise都是reject的,那么也会等到所有的Promise都变成rejected状态;
const p1 = new Promise((resolve,reject) => {
reject('message error p1')
// resolve('p1 info')
})
const p2 = new Promise((resolve,reject) => {
reject('message error p2')
// resolve('p2 info')
})
const p3 = new Promise((resolve,reject) => {
// reject('message error1 p3')
resolve('p3 info')
})
Promise.any([p1,p2,p3]).then(res => {
console.log(res)//p3 info
}).catch(err => {
console.log(err)
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
- 如果所有的Promise都是rejected状态,那么会报一个AggregateError的错误。
const p1 = new Promise((resolve,reject) => {
reject('message error p1')
// resolve('p1 info')
})
const p2 = new Promise((resolve,reject) => {
reject('message error p2')
// resolve('p2 info')
})
const p3 = new Promise((resolve,reject) => {
reject('message error1 p3')
// resolve('p3 info')
})
Promise.any([p1,p2,p3]).then(res => {
console.log(res)
}).catch(err => {
console.log(err)//[AggregateError: All promises were rejected]
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18