You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

使用async/await与Express路由时遇TypeError及未处理Promise拒绝问题

Fixing Unhandled Promise Rejections with Express & Async/Await

Hey there! Let's work through the unhandled Promise rejection issue you're hitting, plus tidy up that client-side login code to avoid common pitfalls.

First, Let's Fix the Client-Side Code

Looking at your snippet, there are a few small issues that could be triggering those unhandled rejections:

  1. Typos & Unfinished Code
    You have console.log(respon... which is a truncated variable name—should be console.log(response). A typo like this will throw an error that isn't caught, leading to an unhandled Promise rejection.

  2. Fetch Doesn't Reject on HTTP Errors
    By default, the fetch API only rejects if there's a network failure. HTTP errors (like 401 Unauthorized or 500 Server Error) still resolve successfully, but with response.ok set to false. If you don't check this, your code might behave unexpectedly, and any errors from the server won't be properly handled.

  3. Unsafe URL Parameter Concatenation
    Directly appending username/password to the URL can cause encoding issues (e.g., if a user has special characters in their credentials). Use URLSearchParams instead for safe parameter handling.

Here's the corrected client-side code with proper error handling:

async function signIn() {
  try {
    const username = document.getElementById('username').value;
    const password = document.getElementById('password').value;
    
    // Use URLSearchParams for safe query string handling
    const params = new URLSearchParams({ username, password });
    const url = `/api/login?${params}`;

    const response = await fetch(url);

    // Check if the request was successful
    if (!response.ok) {
      // Throw an error with the status text/response to handle it in catch
      throw new Error(`Login failed: ${response.statusText}`);
    }

    const data = await response.json(); // Parse the response data
    console.log('Login successful:', data);
    // Add your post-login logic here (e.g., redirect to dashboard)
  } catch (error) {
    // Catch ALL errors: network issues, typos, HTTP errors, etc.
    console.error('Login error:', error.message);
    // Show an error message to the user here
  }
}

Now, Fixing Express Backend Unhandled Rejections

On the Express side, if you're using async functions as route handlers, Express won't automatically catch Promise rejections. You need to either:

Option 1: Wrap Async Logic in Try/Catch

// Express route example
app.get('/api/login', async (req, res) => {
  try {
    const { username, password } = req.query;
    // Your login logic (e.g., check database)
    const user = await User.findOne({ username, password });
    
    if (!user) {
      return res.status(401).json({ message: 'Invalid credentials' });
    }

    res.json({ message: 'Login successful', user });
  } catch (error) {
    // Handle any errors (e.g., database connection issues)
    console.error('Server error:', error);
    res.status(500).json({ message: 'Server error' });
  }
});

Option 2: Use an Async Error Wrapper Middleware

If you don't want to write try/catch for every route, create a wrapper function to catch rejections and pass them to Express's error handler:

const asyncHandler = (fn) => (req, res, next) => {
  Promise.resolve(fn(req, res, next)).catch(next);
};

// Use it in your route
app.get('/api/login', asyncHandler(async (req, res) => {
  const { username, password } = req.query;
  const user = await User.findOne({ username, password });
  
  if (!user) {
    return res.status(401).json({ message: 'Invalid credentials' });
  }

  res.json({ message: 'Login successful', user });
}));

// Don't forget to add a global error handler at the end of your middleware stack
app.use((err, req, res, next) => {
  console.error('Global error:', err);
  res.status(500).json({ message: 'Something went wrong' });
});

Key Takeaways

  • Always wrap async/await code in try/catch to handle errors and avoid unhandled Promise rejections.
  • For fetch, explicitly check response.ok to handle HTTP errors.
  • In Express, either use try/catch in async routes or an error wrapper middleware to pass errors to the global handler.

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

火山引擎 最新活动