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

Promise在前端开发中用的很多了,感觉好像很熟了,但真的有些细节追究起来好像又有点是是而非。

今天聊聊Promise中的then和catch,以下面这个代码片段为例,如果能正确说出打印的内容,说明已经掌握了,后面的内容就可以不用看了。

javascript 复制代码
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);
  });

答案是:先后打印

javascript 复制代码
  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时要执行的回调函数。

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

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

javascript 复制代码
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中接收的回调函数

javascript 复制代码
new Promise((resolve, reject) => {
  reject('error');
}).catch((err) => {
  console.log(err);
});
2.1 catch和then的关系

catch可以理解为Promise.prototype.then(undefined,rejectedCallback)的一个语法糖,

即下面两段代码是等效的

javascript 复制代码
new Promise((resolve, reject) => {
  reject('error');
}).then(undefined, (err) => {
  console.log(err);
});
javascript 复制代码
new Promise((resolve, reject) => {
  reject('error');
}).catch((err) => {
  console.log(err);
});
2.3catch方法的返回

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

最后来解释开头中的题目

javascript 复制代码
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);
  });
相关推荐
Lysun00136 分钟前
dispaly: inline-flex 和 display: flex 的区别
前端·javascript·css
山禾女鬼0011 小时前
Vue 3 自定义指令
前端·javascript·vue.js
啊卡无敌1 小时前
Vue 3 reactive 和 ref 区别及 失去响应性问题
前端·javascript·vue.js
涵信1 小时前
第九节:React HooksReact 18+新特性-React 19的use钩子如何简化异步操作?
前端·javascript·react.js
我是仙女你信不信2 小时前
生成pdf并下载
前端·javascript·vue.js
vvilkim2 小时前
React 组件类型详解:类组件 vs. 函数组件
前端·javascript·react.js
啊吧啊吧曾小白3 小时前
作用域、闭包与this指向问题
前端·javascript·面试
HiF3 小时前
Hexo博客集成LivePhoto
javascript
八了个戒3 小时前
「数据可视化 D3系列」入门第七章:坐标轴的使用
前端·javascript·数据可视化·canvas·d3
八了个戒3 小时前
「数据可视化 D3系列」入门第二章:选择器与数据绑定
前端·javascript·数据可视化·canvas·d3