聊聊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);
  });
相关推荐
宝子向前冲34 分钟前
React中九大常用Hooks总结
前端·javascript·react.js
F-1254 小时前
关于 vue/cli 脚手架实现项目编译运行的源码解析
前端·javascript·vue.js
web喵神5 小时前
react-pdf预览在线PDF的使用
javascript·web前端·插件·移动端开发
一直在学习的小白~5 小时前
基于React通用的 WebSocket 钩子 useWebSocket
javascript·websocket·react.js
战族狼魂6 小时前
vue axios 如何读取项目下的json文件
javascript·vue.js·json
星河路漫漫6 小时前
JavaScript高阶面试题:(第三天)
java·javascript·面试
加勒比海涛8 小时前
掌握 JavaScript ES6+:现代编程技巧与模块化实践
开发语言·javascript·es6
暴富暴富暴富啦啦啦9 小时前
el-table 的单元格 + 图表 + 排序
javascript·vue.js·elementui
花下的晚风10 小时前
Vue实用操作-2-如何使用网页开发者工具
前端·javascript·vue.js
安冬的码畜日常10 小时前
【D3.js in Action 3 精译_022】3.2 使用 D3 完成数据准备工作
前端·javascript·信息可视化·数据挖掘·数据可视化·d3.js