ES6 --- Promise

概述

概念上说,Promise是异步编程的一种解决方案。

从语法上说,Promise是一个对象,可以从他获取异步操作的消息。

状态

Promise对象有三种状态:

1. pending (进行中)

2. fulfilled(已成功)

3. rejected (已失败)

  > 特点

  Promise对象有两个特点:

  1. 对象的状态不受外界印象。Promise对象的状态只有异步操作的结果可以决定

  2. 对象的状态改变就不会再变。Promise对象有两种状态改变,一是从pending到resolved,二是从pending到rejected。这两种状态只要发生一种,就会一直保持这个结果。

  > 缺点

  1. Promise一旦执行,无法取消。

  2. Promise如果不设置回调函数,其内部抛出的错误不会反应到外部

  3. pending状态,无法得知目前进展到哪一个阶段

参数

Promise接受一个函数作为参数,这个函数的两个参数分别是resolve和reject。

1. resolve -> 将Promise对象的状态从pending变为resolved,并且将异步操作成功返回的结果作为参数传递出去

2. reject -> 将Promise对象的状态从pending变为 rejected,并且将异步操作返回的错t误作为参数传递出去

then方法

then方法接收两个函数作为参数,第一个参数是resolved状态的回调函数,第二个参数是rejected状态的回调函数。两个函数只有一个会被调用。

 1 let p  = new Promise((resolve,reject) => {
 2     resolve() 
 3 })
 4 p.then(() => {
 5     console.log("then方法的第一个参数")
 6 },() => {
 7     console.log("then方法的第二个参数")
 8 })
 9 .catch(() => {
10     console.log("catch方法")
11 })

结果输出: 

  then方法的第一个参数

 1 let p  = new Promise((resolve,reject) => {
 2     reject()
 3 })
 4 p.then(() => {
 5     console.log("then方法的第一个参数")
 6 },() => {
 7     console.log("then方法的第二个参数")
 8 })
 9 .catch(() => {
10     console.log("catch方法")
11 })

结果输出:  

  then方法的第二个参数
 
 
then方法返回一个新的Promise实例(不是之前那个),故此可以写成链式调用,then方法之后再调用另一个then方法。这样的写法可以指定一组按照次序调用的回调函数,因为如果前面一个回调函数返回的依然是一个promise对象,那么下一个回调函数就会等待这个Promise的状态结果才调用。
 1 let p  = new Promise((resolve,reject) => {
 2     setTimeout(() => {
 3         console.log("Promise ----- p")
 4         resolve()
 5     },1000)
 6 })
 7 let p1 = new Promise((resolve,reeject) =>{
 8     console.log("Promise ----- p1")
 9     resolve(p)
10 })
11 p1.then(res => {
12     console.log("then方法的第一个参数")
13 })
14 .catch(() => {
15     console.log("catch方法")
16 })

返回结果的输出顺序:

  Promise ----- p1

  (两次输出之间间隔1秒)
  Promise ----- p
  then方法的第一个参数

 链式调用

 1 let p  = new Promise((resolve,reject) => {
 2     resolve()
 3 })
 4 p.then(() => {
 5     console.log("第一个then方法")
 6 })
 7 .then(() => {
 8     console.log("第二个then方法")
 9 })
10 .then(() => {
11     console.log("第三个then方法")
12 })
13 .then(() => {
14     console.log("第四个then方法")
15 })
16 .then(() => {
17     console.log("第五个then方法")
18 })

输出结果:

  第一个then方法
  第二个then方法
  第三个then方法
  第四个then方法
  第五个then方法
 

catch方法

发生错误时的回调函数。Promise对象的错误具有向后传递的性质,前面的错误(包括then方法中的错误或者前面一个catch中的错误)总是会被下一个catch捕获(捕获前面没有被捕获的错误,包括then的回调函数中抛出的错误)。

 
1 let p  = new Promise((resolve,reject) => {
2     reject()
3 })
4 p.then(() => {
5     console.log("then方法的第一个参数")
6 })
7 .catch(() => {
8     console.log("catch方法")
9 })

结果输出:

  catch方法

  

catch捕捉then方法中的错误

 1 let p  = new Promise((resolve,reject) => {
 2     resolve()
 3 })
 4 p.then(() => {
 5     console.log("then方法的第一个参数")
 6     throw new Error("then 错误")
 7 })
 8 .catch(() => {
 9     console.log("catch方法")
10 })

输出结果: 

  then方法的第一个参数
  catch方法

catch向后传递的特性

 1 let p  = new Promise((resolve,reject) => {
 2     reject()
 3 })
 4 p.then(() => {
 5     console.log("then方法的第一个参数")
 6 })
 7 .catch(() => {
 8     console.log("第一个catch方法")
 9     throw new Error("catch错误")
10 })
11 .then(() => {
12     console.log("第二个then方法")
13 })
14 .catch(() => {
15     console.log("第二个catch")
16 })

输出结果:

  第一个catch方法
  第二个catch

   

finally方法

不管Promise对象的状态是什么都会执行的操作。finally方法的回调函数不接受任何参数,则没有办法知道前端Promise的具体状态,换句话说finally不依赖于Promise的执行结果

 1 let p  = new Promise((resolve,reject) => {
 2     resolve()
 3 })
 4 p.then(() => {
 5     console.log("第一个then方法")
 6 })
 7 .catch(() => {
 8     console.log("第一个catch方法")
 9 })
10 .finally(() => {
11     console.log("finally")
12 })

输出结果:  

  第一个then方法

  finally

 1 let p  = new Promise((resolve,reject) => {
 2    reject()
 3 })
 4 p.then(() => {
 5     console.log("第一个then方法")
 6 })
 7 .catch(() => {
 8     console.log("第一个catch方法")
 9 })
10 .finally(() => {
11     console.log("finally")
12 })

输出结果:  

  第一个catch方法

  finally

all方法

all方法用于将多个Promise实例包装成一个新的Promise实例。新的Promise实例的状态由组成它的Promise实例的状态共同决定(个人感觉有点类似于&&运算符)。

1> 多个Promise实例的状态都变成已完成(resolved)状态,新的Promise实例的状态才会变成已完成状态,并且将多个Promise实例的返回值组成一个数组传递给新的Promise的回调函数

2> 多个Promise实例中,只要有一个实例的状态变成rejected,新的实例的状态就会变成rejecte,并且将第一个状态为rejected的实例的返回值传递给新的Promise实例的回调函数。

 1 let p1  = new Promise((resolve,reject) => { 3     resolve("p1")
 4 })
 5 let p2  = new Promise((resolve,reject) => { 7     resolve("p2")
 8 })
 9 let p3  = new Promise((resolve,reject) => {11     resolve("p3")
12 })
13 
14 let p  = Promise.all([p1,p2,p3])
15 p.then(res => {
16     console.log('返回结果res -->',res)
17 })
18 .catch((error) => {
19     console.log('返回错误error -->',error)
20 })

输出结果:

  返回结果res --> (3) ["p1", "p2", "p3"]

 1 let p1  = new Promise((resolve,reject) => { 3     resolve("p1")
 4 })
 5 let p2  = new Promise((resolve,reject) => { 7     reject("p2")
 8 })
 9 let p3  = new Promise((resolve,reject) => {11     resolve("p3")
12 })
13 
14 let p  = Promise.all([p1,p2,p3])
15 p.then(res => {
16     console.log('返回结果res -->',res)
17 })
18 .catch((error) => {
19     console.log('返回错误error -->',error)
20 })

输出结果:

  返回错误error --> p2

race方法

跟all方法相同,将多个Promise实例包装成一个新的Promise实例,只不过和all方法不同的是,race是哪个Promise先返回结果就取哪个Promise的结果,不会等待全部的Promise实例执行完。

all方法返回的结果和参数中数组的有关系,但是race方法的返回结果和Promise实例的执行顺序有关。

 1 let p1  = new Promise((resolve,reject) => {
 2     resolve("p1")
 3 })
 4 let p2  = new Promise((resolve,reject) => {
 5     resolve("p2")
 6 })
 7 let p3  = new Promise((resolve,reject) => {
 8     resolve("p3")
 9 })
10 
11 let p  = Promise.race([p1,p2,p3])
12 p.then(res => {
13     console.log('返回结果res -->',res)
14 })
15 .catch((error) => {
16     console.log('返回错误error -->',error)
17 })

输出结果:

  返回结果res --> p1

 1 let p1  = new Promise((resolve,reject) => {
 2     setTimeout(() => {
 3         resolve("p1")
 4     },1000)
 5 })
 6 let p2  = new Promise((resolve,reject) => {
 7     setTimeout(() => {
 8         resolve("p2")
 9     },1500)
10 })
11 let p3  = new Promise((resolve,reject) => {
12     setTimeout(() => {
13         reject("p3")
14     },500)
15 })
16 
17 let p  = Promise.race([p1,p2,p3])
18 p.then(res => {
19     console.log('返回结果res -->',res)
20 })
21 .catch((error) => {
22     console.log('返回错误error -->',error)
23 })

输出结果:

  返回错误error --> p3

小记:

catch和then方法的第二个参数的区别:

我们知道,then方法的是第二个参数和catch都是Promise状态变为rejected时执行的回调函数,但是我们一般不用then方法的第二个参数而总是使用catch方法,这是因为catch方法可以捕获到then方法中的错误,而then方法的第二个参数是捕捉不到的。

...

原文地址:https://www.cnblogs.com/wangrenmeng/p/10904855.html