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

如何在Axios调用中正确抛出追加AppB错误的异常并避免超时?

Fixing Axios Catch Error Propagation with Stack Traces in Express

Let's break down what's causing your issues and fix them step by step:

What's Wrong With Your Current Code?

  1. Unsent Successful Response: In your then block, you're just returning data.data instead of sending it to the client with res.send(). This means even successful calls will timeout because the client never gets a response.
  2. Uncaptured Async Error: When you throw e in the catch block, you're rejecting the Promise returned by the route handler. Older Express versions don't automatically handle rejected Promises from route handlers, leading to the UnhandledPromiseRejectionWarning.
  3. Broken Stack Trace Handling: You're creating a string with the combined stack trace but never assigning it back to e.stack—so your new error doesn't actually include the AppB error details.

Step-by-Step Fix

1. Update AppB to Return Structured Errors

First, make sure AppB sends a JSON-formatted error with both message and stack trace, so AppA can parse it easily:

// AppB route
api.get('/', (req, res) => {
  const err = new Error('B');
  res.status(500).json({
    message: err.message,
    stack: err.stack
  });
});

// Add Express error-handling middleware to AppB (to catch all errors)
api.use((err, req, res, next) => {
  res.status(500).json({
    message: err.message,
    stack: err.stack
  });
});

2. Fix AppA's Route Handler

We'll use async/await to make async error handling cleaner (Express will automatically pass async errors to your error middleware):

// AppA route (using async/await)
api.get('/', async (req, res, next) => {
  try {
    // Fetch data from AppB
    const axiosResponse = await axios({
      method: "GET",
      url: "http://localhost:3060/api/"
    });
    // Send successful response to client
    res.send(axiosResponse.data);
  } catch (err) {
    // Extract AppB's error from the axios response
    const appBError = err.response?.data || { message: 'Unknown AppB error' };
    
    // Create new error with custom message
    const wrappedError = new Error(`Rethrowing the "${appBError.message}" error FROM A`);
    
    // Merge stack traces: keep our new error's top 2 lines, then append AppB's error details
    if (wrappedError.stack) {
      wrappedError.stack = [
        // Keep the first two lines of our new error (message + immediate stack frame)
        ...wrappedError.stack.split('\n').slice(0, 2),
        '--- AppB Error Details ---',
        appBError.message,
        ...(appBError.stack ? appBError.stack.split('\n') : [])
      ].join('\n');
    }
    
    // Throw the wrapped error—Express will pass it to your error middleware
    throw wrappedError;
  }
});

3. Add Error-Handling Middleware to AppA

This ensures all errors (including our wrapped one) are sent to the client properly instead of timing out:

// AppA error-handling middleware (place this after all routes)
api.use((err, req, res, next) => {
  console.error('Full error stack:', err.stack);
  res.status(500).json({
    message: err.message,
    stack: err.stack
  });
});

Alternative: Without Async/Await

If you prefer to keep the Promise chain, replace throw e with next(e) to manually pass the error to Express's middleware:

api.get('/', (req, res, next) => {
  return axios({ method: "GET", url: "http://localhost:3060/api/" })
    .then((axiosResponse) => {
      res.send(axiosResponse.data);
    })
    .catch((err) => {
      const appBError = err.response?.data || { message: 'Unknown AppB error' };
      const wrappedError = new Error(`Rethrowing the "${appBError.message}" error FROM A`);
      
      if (wrappedError.stack) {
        wrappedError.stack = wrappedError.stack.split('\n').slice(0,2).join('\n') +
          '\n--- AppB Error Details ---\n' +
          appBError.message +
          (appBError.stack ? '\n' + appBError.stack : '');
      }
      
      // Pass error to Express middleware
      next(wrappedError);
    });
});

What This Fixes

  • No more UnhandledPromiseRejectionWarning because errors are properly captured by Express.
  • Clients get a timely response (no more timeouts) whether the call succeeds or fails.
  • The returned error includes both AppA's context and AppB's full error message + stack trace.

内容的提问来源于stack exchange,提问作者twcardenas

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.06 13:22:31