You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何修改代码避免内部Try报错导致外层Try的返回被取消?

问题

我正在尝试发送API请求创建文档,在将文档返回给用户前,需执行另一个fetch方法将文档发送至其他端点。若该端点请求失败,我仍希望将原始文档返回给用户,但目前失败时用户无法收到响应,不确定如何无问题地实现需求。

需求流程:

  1. 外层Try块:
    • 创建文档
    • 内层Try块:
      • 将文档发送至目标端点
      • 若成功,更新数据库中的文档
      • 若失败:继续执行(当前此处失效)
      • 内层Catch块:仅打印错误,不抛出异常
    • 必须返回原始文档给用户(内层Try失败时也不能中断)
  2. 外层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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 22:35:22