关于promise链式调用的错误捕捉(见描述)?

目前有这样的需求,页面上有两个按钮---保存和提交,点击保存的时候,会调用保存接口,点击提交的时候回先调用保存接口然后调用提交接口。然后我就写成如下:

// 点击保存按钮的时候
save () {
   // 请求保存接口
   axios.get(...).then(){
    // 消息提示
   }.catch(error) {
     处理错误信息
   }
}

// 请求提交接口
commit () {
  axios.get(...).then() {
    // ....
  }.catch(error) {
    // 错误处理
  }
}

confirm () {
  // 先请求保存接口
   axios.get(...).then(){
    // 调用提交接口
    this.commit()
   }.catch(error) {
     处理错误信息
   }
}

一开始我是这么写的,因为也就2个接口链式,但是后来我仔细一想这样写的话,不就是回调地狱的写法了吗,在then的回调函数里调用函数。

所以我改写成

// 点击保存按钮的时候
save () {
   // 请求保存接口
   axios.get(...).then(){
    // 消息提示
   }.catch(error) {
     处理错误信息
   }
}

// 请求提交接口
commit () {
  return axios.get(...)
}

confirm () {
  // 先请求保存接口
   axios.get(...).then(){
    // 调用提交接口
    return this.commit()
   }.then() {
     
   }.catch(error) {
     // 错误处理
   }
}

但是这样我想到一个问题,他后面这个catch捕获的是保存接口的报错还是提交接口的报错呢?

总所周知then和catch都会返回promise,如果就是就近的使用catch捕捉,那么后面的then方法会运行造成不可预料的错误

阅读 3.2k
3 个回答

// 看你想怎么捕捉了
// 一个promise 异常会被就近的catch捕捉

save () {
   // 请求保存接口
   return axios.get(...).catch(error) {
       //  单独处理   
   }
}

// 请求提交接口
commit () {
  return axios.get(...).catch(...)
}

confirm () {
   this.save().then(){
    return this.commit()
   }.then(){}.catch(error) {
     // 这里是不会来的 因为 上面都捕捉完了
   }
}

// 验证

function axios() {
  return new Promise((resolve, reject) => {
    setTimeout(resolve, 3000)
    // setTimeout(reject, 3000)
  })
}
function commit() {
  return axios().catch(() => {
    console.log(1)
  })
}
function save() {
  return axios().catch(() => {
    console.log(2)
  })
}

function confirm  () {
  commit().then(() => {
    // 这里判断是否时序需要执行save
    console.log(3);
    return save()
  }).then(() => {
    console.log(4);
  }).catch(() =>{
    console.log(5);
  })
}
confirm()

//setTimeout(resolve, 3000)
打印 3 4

// setTimeout(reject, 3000)
打印 1 3 2 1

换一个写法

axios.get(...)
.then(this.save) // save和commit但凡有一个方法中catch了,那么这个链路下面的catch都不会捕捉到所以catch要控制好,不然什么地方断的你都不知道
.then(this.commit)
.catch(e => {})

他后面这个 catch 捕获的是保存接口的报错还是提交接口的报错呢?

这个问题取决于保存接口提交接口有没有设置捕捉错误方法。
1 如果保存接口提交接口都设置了捕获错误函数,则最后面的 catch 方法不会捕获保存接口提交接口中的错误.

confirm () {
  // 先请求保存接口
   axios.get(...).then(() => {
    // 调用提交接口
    return this.commit().catch(e => { //捕获提交接口中的错误})
   })
   .catch(e => {
        //捕获保存接口中的错误
    })
   .then() {
     
   }.catch(error) {
     //不会捕获保存接口和提交接口中的错误
   }
}

2 保存接口提交接口都没有设置捕获错误函数,则最后面的 catch 方法捕获保存接口提交接口中的错误。

confirm () {
  // 先请求保存接口
   axios.get(...).then(() => {
    // 调用提交接口
    return this.commit()
   })
   .then() {
     
   }.catch(error) {
     //捕获的错误即可能是保存接口中的错误,也可能是提交接口中的错误.
   }
}

3 如果保存接口设置了捕获错误函数,提交接口没有设置,则最后面的 catch 方法会捕获提交接口中的错误

confirm () {
  // 先请求保存接口
   axios.get(...).then(() => {
    // 调用提交接口
    return this.commit()
   })
   .catch(e => {
        //捕获保存接口中的错误,如果保存接口没有抛出错误,则捕获提交接口中的错误
    })
   .then() {

   }.catch(error) {
     // 都不会捕获
   }
}

4 如果保存接口方法没有设置捕获错误函数,而提交接口有设置,则最后面的 catch 方法会捕获保存接口中的错误, 如果保存接口抛出错误,则提交接口不会执行。

confirm () {
  // 先请求保存接口
   axios.get(...).then(() => {
    // 调用提交接口
    return this.commit().catch(e => { //捕获提交保存接口中的错误})
   })
   .then() {
     
   }.catch(error) {
     //捕获保存接口中的错误
   }
}
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题