为何已用.catch()仍出现Cannot set headers after they are sent to the client错误?
问题
我用fetch()从API获取数据,成功时用.then()处理,出错时用.catch()捕获,代码如下:
let data; await fetch(API + "/demo/demo", { method: "POST", headers: { "Content-Type": "application/json" }, body: body, }) .then(async (result) => { data = await result.json(); }) .catch((error) => { return res.status(500).render("errors/500", { document: "Error", message: error.message, }); }); if (!data) { return res.status(500).render("errors/500", { document: "Error", message: "No Data", }); }
说明:
let data作为占位符,在.then()完成后赋值.catch()用于捕获fetch(API)的错误if(!data)用于处理无数据的情况并返回错误
现在出现了"Cannot set headers after they are sent to the client"错误,原因是.catch()已经返回了响应,但if(!data)又返回了一次响应。我试过移除.catch()或者仅赋值error.message不返回,暂时解决了问题,但我以为.catch()中的return会终止后续代码执行,if(!data)不会执行,想知道原因和解决办法。
原因解释
.catch()里的return只是终止当前回调函数的执行,不会阻止后续代码运行。因为你用await等待整个fetch().then().catch()的Promise链完成,不管.catch()有没有触发,await都会等到整个Promise链结束,之后的if(!data)代码还是会继续执行。- 当
fetch出错进入.catch(),你已经通过res.status(500).render()发送了响应,但此时data还是undefined,后续if(!data)判断会再次发送响应,这就导致了重复设置响应头的错误。
解决建议
方案1:改用try/catch(更清晰,推荐)
直接用try/catch替代Promise的.then()和.catch(),出错时的return会直接跳出当前函数,避免后续代码执行:
let data; try { const result = await fetch(API + "/demo/demo", { method: "POST", headers: { "Content-Type": "application/json" }, body: body, }); data = await result.json(); } catch (error) { return res.status(500).render("errors/500", { document: "Error", message: error.message, }); } if (!data) { return res.status(500).render("errors/500", { document: "Error", message: "No Data", }); }
方案2:把逻辑整合到Promise链中
将if(!data)的判断放到.then()里,所有逻辑都在Promise链内完成,避免全局变量和后续代码触发重复响应:
await fetch(API + "/demo/demo", { method: "POST", headers: { "Content-Type": "application/json" }, body: body, }) .then(async (result) => { const data = await result.json(); if (!data) { return res.status(500).render("errors/500", { document: "Error", message: "No Data", }); } // 这里处理data存在的业务逻辑 }) .catch((error) => { return res.status(500).render("errors/500", { document: "Error", message: error.message, }); });
内容的提问来源于stack exchange,提问作者Cosmos Lee
相关产品推荐
相关产品推荐

