如何修改代码避免内部Try报错导致外层Try的返回被取消?
问题
我正在尝试发送API请求创建文档,在将文档返回给用户前,需执行另一个fetch方法将文档发送至其他端点。若该端点请求失败,我仍希望将原始文档返回给用户,但目前失败时用户无法收到响应,不确定如何无问题地实现需求。
需求流程:
- 外层Try块:
- 创建文档
- 内层Try块:
- 将文档发送至目标端点
- 若成功,更新数据库中的文档
- 若失败:继续执行(当前此处失效)
- 内层Catch块:仅打印错误,不抛出异常
- 必须返回原始文档给用户(内层Try失败时也不能中断)
- 外层Catch块:抛出异常
现有代码:
try { const document = await prisma.document.create( { data: { //... } }, ); try { //TRY OPTIONAL ENDPOINT const tryEndpoint = () => { return new Promise((resolve, reject) => { fetch(`${process.env.ENDPOINT}`, { method: 'POST', headers: { 'Content-Type': 'text/xml; charset=utf-8', SOAPAction: 'Insert', }, body: body, }) .then((response) => { return response.text(); }) .then((text) => { parseString(text, function (err: any, result: any) { if (err) { reject(err); } console.log(JSON.stringify(result, null, 2)); if ( result['SOAP-ENV:Envelope']?.['SOAP-ENV:Body']?.[0]?.[ 'tns:Result' ]?.[0]?.['tns:Status']?.[0] === 'OK' ) { console.log('OK'); resolve(true); } else { console.log('ERROR'); resolve(false); } }); return null; }) .catch((err) => { console.error(err); }); }); }; //DO NOT STOP IF ENDPOINT FAILS const didSendToEnpoint = await tryEndpoint(); if (didSendToEnpoint) { await prisma.document.update({ where: { id: +id }, data: { didTryEndpoint: true, }, }); } } catch (error) { console.log(error); } //MUST RETURN IF OPTIONAL ENDPOINT FAILS return personDocumentStatus; } catch (error) { console.error(JSON.stringify(error, null, 2)); if (error instanceof Error) { throw new Error(error.message); } } }, },
解决方案
核心问题在于tryEndpoint函数的Promise未正确处理所有失败场景,导致Promise挂起、await无限等待,最终阻塞返回逻辑。以下是具体修改方案:
1. 修复Promise错误处理
原fetch的.catch仅打印错误但未调用reject,导致Promise一直处于pending状态,await tryEndpoint()永远无法完成。需确保所有错误分支都能触发resolve/reject,避免Promise挂起。
2. 重构tryEndpoint为async函数
用async/await替代链式调用,简化代码结构,错误处理更直观。
3. 确保返回正确的文档对象
原代码返回personDocumentStatus,需确认该变量为创建好的文档;若不是,直接返回document更符合需求。
修改后的完整代码
try { const document = await prisma.document.create({ data: { //... 你的数据定义 }, }); try { const tryEndpoint = async () => { try { const response = await fetch(`${process.env.ENDPOINT}`, { method: 'POST', headers: { 'Content-Type': 'text/xml; charset=utf-8', SOAPAction: 'Insert', }, body: body, }); const text = await response.text(); // 将parseString包装为Promise,消除回调嵌套 const result = await new Promise((resolve, reject) => { parseString(text, (err, parsedResult) => { if (err) reject(err); else resolve(parsedResult); }); }); console.log(JSON.stringify(result, null, 2)); const status = result['SOAP-ENV:Envelope']?.['SOAP-ENV:Body']?.[0]?.['tns:Result']?.[0]?.['tns:Status']?.[0]; if (status === 'OK') { console.log('OK'); return true; } else { console.log('ERROR: 端点返回非OK状态'); return false; } } catch (err) { console.error('端点请求失败:', err); // 失败时返回false,避免触发内层catch return false; } }; const didSendToEnpoint = await tryEndpoint(); if (didSendToEnpoint) { await prisma.document.update({ where: { id: document.id }, // 直接使用创建的文档ID,避免外部变量依赖 data: { didTryEndpoint: true, }, }); } } catch (error) { console.log('内层处理异常:', error); // 仅打印错误,不中断流程 } // 确保返回创建好的文档 return document; // 若personDocumentStatus是正确返回值,替换为该变量 } catch (error) { console.error(JSON.stringify(error, null, 2)); if (error instanceof Error) { throw new Error(error.message); } // 兜底处理非Error类型的异常 throw new Error('未知错误'); }
关键修改说明
- 将
parseString包装为Promise,确保解析错误能被捕获,避免回调嵌套。 - 处理fetch请求的所有错误(网络错误、解析错误等),保证Promise不会挂起。
- 内层try/catch捕获所有
tryEndpoint异常,打印后继续执行返回逻辑,不阻塞用户响应。 - 使用
document.id替代+id,避免依赖外部变量,提升代码可靠性。
内容的提问来源于stack exchange,提问作者SlothOverlord
相关产品推荐
相关产品推荐

