我们相信:世界是美好的,你是我也是。平行空间的世界里面,不同版本的生活也在继续...

JavaScript里面,promise是个异步请求。如果所内嵌的逻辑里面,抛出了异常信息。如何处理服务器的返回值呢?面对服务器错误信息,如何捕获错误呢?苏南大叔在本文中将总结promise的异常捕获解决方案。

苏南大叔:JavaScript,如何捕获promise的reject()异常返回值信息? - 请求远程接口
JavaScript,如何捕获promise的reject()异常返回值信息?(图5-1)

苏南大叔的“程序如此灵动”博客,记录苏南大叔的编程经验文章。测试环境:chrome@131.0.6778.70nodejs@20.18.0。本文描述的是对于promise的异常处理方案。任何一个变量或者函数返回值,只要类型被判定为promise,都适用于本文的内容。

promise抛出异常

下面的代码中,将有一个promise内部抛出一个error

const sunan = (...args) => {
  return new Promise((resolve, reject) => {
    let rand = Math.random();
    if (rand > 0.8) {
      resolve({ ok: true });
    } else if (rand > 0.5) {
      reject({ code: "-1", msg: "逻辑错误 Json" });
    } else if (rand > 0.25) {
      reject("自定义错误 String");
    } else {
      reject(new Error("意外错误 Error"));
    }
  });
};

这个例子里面,成功的方式就是resolve({})。而发生错误的方式,这里使用了三种不同的方式。参见下表。

语句返回值类型抛出错误解析方式
reject(new Error("e"))stringe.message
reject("s");string×e 或 JSON.parse(e)
reject({});object×e

这里的reject()无论返回值是什么,都是发生了错误,在后续的逻辑处理里面,这三种情况都属于发生了异常,需要被捕获处理。

苏南大叔:JavaScript,如何捕获promise的reject()异常返回值信息? - reject返回值
JavaScript,如何捕获promise的reject()异常返回值信息?(图5-2)

异常捕获之try-catch-finally

try-catch万能大法,捕获一切异常。如果对应的promiseresolve()reject()的话,直接不try catch,仅仅await也是可以的。

(async () => {
  let data = await sunan();
  console.log("Promise返回值:", data);
})();

只是突发异常的情况不能捕获了而已。(trycatch不仅仅捕获error异常,还可以捕获reject({})的情况)

苏南大叔:JavaScript,如何捕获promise的reject()异常返回值信息? - trycatch截图
JavaScript,如何捕获promise的reject()异常返回值信息?(图5-3)

(async () => {
  try {
    let data = await sunan();
    console.log("异步函数返回:", data);
  } catch (error) {
    let msg = error?.message ? error.message : error;
    console.log("苏南大叔说:", typeof error, msg);
  } finally {
    // console.log("finally");
  }
})();

异常捕获之.then.catch.finally

也可以使用.then.catch.finally这种三联的方式。

(async () => {
  sunan()
    .then((data) => {
      console.log("Promise返回值:", data);
    })
    .catch((error) => {
      let msg = error?.message ? error.message : error;
      console.log("sunan大叔说:", typeof error, msg);
    })
    .finally(() => {
      // console.log("finally");
    });
})();

苏南大叔:JavaScript,如何捕获promise的reject()异常返回值信息? - 错误信息捕获截图
JavaScript,如何捕获promise的reject()异常返回值信息?(图5-4)

e?.message ? e.message : e

对于错误信息的处理语句e?.message ? e.message : e。这里做个详细的说明。

对于reject(new Error(""))的情况,它被捕获的时候,必须有个e.message字符串属性,用于承载相关信息,这个是系统设定。当然,也可以故意制作一个reject({message:''})的正常返回值,供上述逻辑捕获到。所以,这里的逻辑也并不是没有漏洞。

如果不是上面的情况的话,那么直接e就是返回值,它可以是普通的字符串,也可以是个JSON.stringify()的字符串结果,也可以是个json对象。这个就看具体情况而言了。

链式调用

promise里面链式调用,不管是.then还是.catch,只要return就会进入下一链式环节。只要下一个环节使用参数接收,就能拿到上一个环节的return值。最终链式调用完毕后的return值,就是对这个promise进行await的结果。

这个.then.catch.finally链式调用里面,实际上可以无限组合.then.catch的。比如:

(async () => {
  sunan()
    .then((data) => {
      console.log("promise返回值:", data);
      return data;
    })
    .catch((error) => {
      let msg = error?.message ? error.message : error;
      console.log("sunan大叔说:", typeof error, msg);
      return { modifyby: "sunan" };
    })
    .then((data) => {
      console.log("修正后的值:", data);
      retun data;
    })
    .finally(() => {
      // console.log("finally");
    });
})();

苏南大叔:JavaScript,如何捕获promise的reject()异常返回值信息? - 链式调用then-catch无限组合
JavaScript,如何捕获promise的reject()异常返回值信息?(图5-5)

诀窍就是:不断return 新的值,以及接受“新的值”就行。

远程和本地的error区别

对于.catch()环境,请求接口的状态异常,是不会被catch的,除非在第一个.then里面进行识别,才能被catch到。这个和本地代码里面抛出的error不一样。

假如这里的函数sunan()里面包裹的是个非fetch或者axios之类的远程请求类的promise函数,那么throw error直接进入下面的.catch()

(async () => {
  let ss = await sunan()
    .then((data) => {
      return {"sunan":"ok"};
    })
    .catch((error) => {
      return {"sunan":"error" };
    });
  console.log(ss); //await的结果是链式调用里面最后一个的return值
})();

假如这里的函数sunan()里面包裹的是个fetch或者axios之类的远程请求类的promise函数,那么在服务器端throw error,影响的仅仅是状态码。进入不了.catch()`里面的。

(async () => {
  let ss = await sunan()
    .then((response) => {
      if (!response.ok) {
        throw new Error(`服务器错误,状态码: ${response.status}`); // 主动抛出错误才会被catch
      }
      return response.json();
    })
    .then((data) => {
      return {"sunan":"ok"};
    })
    .catch((error) => {
      return {"sunan":"error" };
    });
  console.log(ss); //await的结果是链式调用里面最后一个的return值
})();

再解释一下:
无论服务器端如何发生错误,状态码如何不正常。只要客户端这边愿意,不检查response.ok,都是不会走到.catch()异常处理那边的。

相关文章

结语

node环境下,本文的内容也是成立的。

如果本文对您有帮助,或者节约了您的时间,欢迎打赏瓶饮料,建立下友谊关系。
本博客不欢迎:各种镜像采集行为。请尊重原创文章内容,转载请保留作者链接。

 【福利】 腾讯云最新爆款活动!1核2G云服务器首年50元!

 【源码】本文代码片段及相关软件,请点此获取更多信息

 【绝密】秘籍文章入口,仅传授于有缘之人   js    node