聊聊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);
  });
相关推荐
默默地写代码6 分钟前
微信小程序 新版canvas绘制名片
前端·javascript·微信小程序
BillKu11 分钟前
Element Plus 对话框 el-dialog 和 抽屉 el-drawer 的使用注意项(使用 div 包裹)
javascript·vue.js·elementui
layman052812 分钟前
Vue 中的配置代理
前端·javascript·vue.js
BillKu19 分钟前
Vue3 + TypeScript 中 hook 优化记录
开发语言·javascript·typescript
未来之窗软件服务22 分钟前
jquery 赋值时不触发change事件解决——仙盟创梦IDE
前端·javascript·jquery·仙盟创梦ide·东方仙盟
AnyaPapa27 分钟前
【解决方案】Vue 常见问题大全
前端·javascript·vue.js
浩宇软件开发1 小时前
JavaScript 数组常用方法 find, findIndex, filter, map, flatMap, some
前端·javascript·vue.js
永生辉皇1 小时前
JS红宝书笔记 8.3 继承
开发语言·javascript·笔记
前端Hardy1 小时前
前端性能飞跃!9大高级API实战指南,80%的开发者只知其三
前端·javascript
永生辉皇2 小时前
JS红宝书笔记 8.2 创建对象
javascript·笔记·原型模式