聊聊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);
  });
相关推荐
一点七加一24 分钟前
Harmony鸿蒙开发0基础入门到精通Day07--JavaScript篇
开发语言·javascript·ecmascript
Anlici5 小时前
连载小说大学生课设 需求&架构
前端·javascript·后端
i源6 小时前
Java语言处理Js文件内容格式化
java·javascript
“负拾捌”7 小时前
基于NodeJs实现一个MCP客户端(会话模式和无会话模式)
javascript·ai·node.js·大模型·mcp
蒜香拿铁7 小时前
Angular【基础语法】
前端·javascript·angular.js
元直数字电路验证8 小时前
ASP.NET Core Web APP(MVC)开发中无法全局配置 NuGet 包,该怎么解?
前端·javascript·ui·docker·asp.net·.net
我有一棵树8 小时前
Vue 项目中全局样式的正确写法:不要把字体和主题写在 #app 上
前端·javascript·vue.js
龙仔CLL9 小时前
微前端乾坤vue3项目使用tinymce,通过npm,yarn,pnpm包安装成功,但是引用报错无法使用
javascript·arcgis·npm
Mountain0810 小时前
解决 Node.js 启动报错:digital envelope routines 错误全记录
javascript·npm·node.js
wangbing112511 小时前
开发指南139-VUE里的高级糖块
前端·javascript·vue.js