JavaScript,如何捕获promise的reject()异常返回值信息?
发布于 作者:苏南大叔 来源:程序如此灵动~
JavaScript里面,promise是个异步请求。如果所内嵌的逻辑里面,抛出了异常信息。如何处理服务器的返回值呢?面对服务器错误信息,如何捕获错误呢?苏南大叔在本文中将总结promise的异常捕获解决方案。

苏南大叔的“程序如此灵动”博客,记录苏南大叔的编程经验文章。测试环境:chrome@131.0.6778.70,nodejs@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")) | string | √ | e.message |
| reject("s"); | string | × | e 或 JSON.parse(e) |
| reject({}); | object | × | e |
这里的reject()无论返回值是什么,都是发生了错误,在后续的逻辑处理里面,这三种情况都属于发生了异常,需要被捕获处理。

异常捕获之try-catch-finally
try-catch万能大法,捕获一切异常。如果对应的promise只resolve()不reject()的话,直接不try catch,仅仅await也是可以的。
(async () => {
let data = await sunan();
console.log("Promise返回值:", data);
})();只是突发异常的情况不能捕获了而已。(trycatch不仅仅捕获error异常,还可以捕获reject({})的情况)

(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");
});
})();
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");
});
})();
诀窍就是:不断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环境下,本文的内容也是成立的。