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
环境下,本文的内容也是成立的。
本博客不欢迎:各种镜像采集行为。请尊重原创文章内容,转载请保留作者链接。