七、Promise对象的深入学习

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、什么是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

# 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
  • 上面Promise使用过程,我们可以将它划分成三个状态:
    • 待定(pending): 初始状态,既没有被兑现,也没有被拒绝;
      • 当执行executor中的代码时,处于该状态;
    • 已兑现(fulfilled): 意味着操作成功完成;
      • 执行了resolve时,处于该状态,Promise已经被兑现;
      • 那么:该Promise实例对象的then方法中的回调函数会执行
    • 已拒绝(rejected): 意味着操作失败;
      • 执行了reject时,处于该状态,Promise已经被拒绝;
      • 那么:该Promise实例对象的catch方法中的回调函数会执行

# 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

# 5、Executor回调函数 - (new Promise(Executor))

  • Executor是在创建Promise实例对象时需要传入的一个回调函数,这个回调函数会被立即执行,并且传入两个参数:
new Promise((resolve,reject) => {
  console.log('executor回调函数内部代码会被立即执行')
})
1
2
3
  • 通常我们会在Executor中确定我们的Promise状态:
    • 通过resolve,可以兑现(fulfilled)Promise的状态,我们也可以称之为已决议(resolved);
    • 通过reject,可以拒绝(reject)Promise的状态;
  • 这里需要注意一旦状态被确定下来,Promise的状态会被 锁死,该Promise的状态是不可更改的
    • 在我们调用resolve的时候,如果resolve传入的值本身不是一个Promise或一个有实现then方法的对象,那么会将该Promise的状态变成 兑现(fulfilled);【如果resolve传入的值是其他值的情况,具体看下面:6、resolve回调函数传入不同值的区别
    • 在之后我们去调用reject时,已经不会有任何的响应了(并不是这行代码不会执行,而是无法改变Promise状态);
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

# 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

# 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

# 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

# 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

# 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 一样理解
    • 情况三:then方法中的回调函数返回一个thenable值;
      • 跟上面new Promise(executor)创建实例对象时,Executor回调函数内部调用resolve回调函数时,传入的值是一个实现了then方法的对象 一样理解
// 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
  • 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

# 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

# 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
  • 那么如果我们希望后续继续执行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

# 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

# 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

# 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

# 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

# 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

# 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

# 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
  • 如果所有的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
最后更新时间: 2022/08/07, 22:02:38
彩虹
周杰伦