聊聊Promise,catch和then的关系,rejected状态如何在then链中”透传“直到被处理

Promise在前端开发中用的很多了,感觉好像很熟了,但真的有些细节追究起来好像又有点是是而非。
今天聊聊Promise中的then和catch,以下面这个代码片段为例,如果能正确说出打印的内容,说明已经掌握了,后面的内容就可以不用看了。

const a = new Promise((resolve, reject) => {
  reject('error');
})
  .then((res) => {
    console.log('res', 1);
  })
  .then(
    (res) => {
      console.log('res', 2);
    },
    (err) => {
      console.log('error', 1);
    }
  )
  .then((res) => {
    console.log('res', 3);
  })
  .catch((err) => {
    console.log('error', 2);
  });

答案是:先后打印

  error 1
  res 3

在这里插入图片描述
Promise的定义和使用方法这里就不做详细说明,主要聊聊then和catch

1. then方法

直接打印Promise对象(使用console.dir),可以看到Promise.prototype中定义了catch、finally、then方法,所以在new Promise后可以调用then、catch等方法
在这里插入图片描述

1.1 then方法接收的参数

then方法可以接收两个参数,一个是Promise状态为Resolved时要执行的回调函数,第二个参数是Promise状态为Rejected时要执行的回调函数。

new Promise((resolve, reject) => {
  resolve(1);
}).then(
  (res) => {
    console.log(res);
  },
  (err) => {
    console.log(err);
  }
);
// 打印 1

由于Promise状态变成了Resolved,所以执行then中的第一个回调函数,函数的参数为resolve的值

new Promise((resolve, reject) => {
  reject('error');
}).then(
  (res) => {
    console.log(res);
  },
  (err) => {
    console.log(err);
  }
);

由于Promise状态变成了Rejected,所以执行then中的第二个回调函数,函数的参数为reject传入的error值。
Q:
日常开发中,我们一般只会在then中传入一个Resolved状态的回调函数。那如果Promise的状态为rejected,但是其后面的then方法又没有定义第二个参数会怎么样?
A:
then会将这个rejected状态的Promise传递下去,直到被某个catch或then的第二个参数处理。后面讲到catch时再具体说明

1.2 then方法的返回

then方法会返回一个Promise对象,Promise对象的状态要根据then执行的回调中(可能是执行的第一个也可能是第二个,具体执行哪一个跟前面返回的Promise对象的状态有关,即1.1中的内容)返回的内容有关:

回调返回内容then方法返回结果
执行的回调中抛出了一个错误返回的是一个Rejected状态的Promise对象,相当于return Promise.reject(error)
执行的回调中return了一个非Promise的值(或者没有return任何内容(undefined))返回的是一个Resolved状态的Promise对象,resolve的值就是return的值
执行的回调中return了一个Promise对象返回的就是return的这个Promise对象
如果then前面的Promise是reject状态,但then中第二个参数未定义返回的是前面这个reject状态的Promise

这里可以参考Promise对象解析(2)then方法
由于then方法始终会返回一个Promise对象所以then后面还可以继续调用then方法形成一个链式效果

2. catch方法

catch方法同样是Promise.prototype的定义的一个方法,用于指定Promise为Rejected状态时执行的回调

2.1 catch方法接收的参数

catch方法接收一个参数,需要传入一个函数,当前面返回的Promise的状态为rejected时,将执行catch中接收的回调函数

new Promise((resolve, reject) => {
  reject('error');
}).catch((err) => {
  console.log(err);
});

2.1 catch和then的关系

catch可以理解为Promise.prototype.then(undefined,rejectedCallback)的一个语法糖,
即下面两段代码是等效的

new Promise((resolve, reject) => {
  reject('error');
}).then(undefined, (err) => {
  console.log(err);
});
new Promise((resolve, reject) => {
  reject('error');
}).catch((err) => {
  console.log(err);
});

2.3catch方法的返回

既然catch是Promise.prototype.then(undefined,rejectedCallback)的一个语法糖,那么他的返回和then是一样的,它也将返回一个Promise对象,Promise对象的状态和其回调中return的内容有关,参考上面then的返回

最后来解释开头中的题目

const a = new Promise((resolve, reject) => {
  reject('error'); //Promise状态变成Rejected
})
  .then((res) => {
    console.log('res', 1);//这里then只传入了一个回调函数,rejected状态不会执行这个回调,then方法会将当前rejected状态Promise对象返回
  })
  .then(
    (res) => {//前面的Promise为rejected状态,此回调不执行
      console.log('res', 2);
    },
    (err) => {//执行
      console.log('error', 1);//由于这里面没有抛出错误,也没任何返回,故then方法会返回一个Resolved状态的Promise对象。resolve值为undefined
    }
  )
  .then((res) => {//执行,因为前面的Promise状态为Resolved,这里res为undefined
    console.log('res', 3);//由于这里面没有抛出错误,也没任何返回,故then方法会返回一个Resolved状态的Promise对象。resolve值为undefined
  })
  .catch((err) => {//前面的Promise状态为Resolved,这里的回调不会执行,catch方法最后会返回一个Resolved状态的Promise对象。resolve值为undefined
    console.log('error', 2);
  });

  • 15
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值