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

如何用JavaScript的fetch方法捕获401错误并实现Token重试

Handling 401 Unauthorized with Fetch: Retry After Token Refresh

Great question! One common gotcha with fetch() is that it doesn’t automatically reject promises for HTTP error status codes like 401—you have to explicitly check the response status in your handler. Here’s a practical way to implement token refresh and request retry for your scenario:

Step-by-Step Implementation

First, let’s refactor your code to include retry logic. We’ll create a reusable helper function to keep things clean:

// Helper function to handle authenticated requests with token refresh
async function fetchWithAuth(url, options = {}) {
  // Initialize headers with your default values
  const headers = new Headers({
    "Accept": "application/json",
    "Content-Type": "application/json",
    ...this.defaultRequestHeaders, // Merge your existing default headers
    ...options.headers // Allow overriding with request-specific headers
  });

  // Add current auth token to headers (replace with your token storage)
  const currentToken = localStorage.getItem('accessToken');
  if (currentToken) {
    headers.set('Authorization', `Bearer ${currentToken}`);
  }

  // Create the initial request
  const initialRequest = new Request(url.toString(), {
    headers,
    method: "get",
    mode: "cors",
    ...options
  });

  try {
    let response = await fetch(initialRequest);

    // Check if we received a 401 Unauthorized
    if (response.status === 401) {
      // 1. Fetch a new token from your token endpoint
      const refreshResponse = await fetch('/api/token-refresh', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json'
        },
        body: JSON.stringify({
          refreshToken: localStorage.getItem('refreshToken') // Use your refresh token
        })
      });

      if (!refreshResponse.ok) {
        // Token refresh failed—redirect to login or handle error
        throw new Error('Refresh token invalid. Please log in again.');
      }

      const newTokenData = await refreshResponse.json();
      const newAccessToken = newTokenData.accessToken;

      // 2. Update stored token for future requests
      localStorage.setItem('accessToken', newAccessToken);

      // 3. Retry the original request with the new token
      const retryRequest = new Request(initialRequest, {
        headers: new Headers(initialRequest.headers) // Copy original headers
      });
      retryRequest.headers.set('Authorization', `Bearer ${newAccessToken}`);

      response = await fetch(retryRequest);
    }

    // Return the final response (original or retried)
    return response;
  } catch (error) {
    console.error('Request failed:', error);
    throw error; // Re-throw so the caller can handle the error
  }
}

// Usage in your code
fetchWithAuth(yourUrl)
  .then(response => {
    if (!response.ok) {
      throw new Error(`HTTP error! Status: ${response.status}`);
    }
    return response.json();
  })
  .then(data => {
    // Your logic to handle the API data
    console.log('Fetched data:', data);
  })
  .catch(error => {
    // Handle errors (e.g., show login prompt if token refresh failed)
    alert(error.message);
  });

Important Considerations

  • Prevent Infinite Loops: Add a retry limit (e.g., only retry once) to avoid looping if the retried request still returns 401. You can modify the helper function to accept a retryCount parameter.
  • Secure Token Storage: Use localStorage with caution (risk of XSS attacks). For better security, consider using HttpOnly cookies for refresh tokens.
  • Handle Edge Cases: If the token refresh endpoint is down or returns an error, redirect the user to the login page instead of retrying.
  • Reuse Request Objects: When retrying, create a new Request instance from the original to avoid mutating the initial headers.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 06:44:20