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

Angular 11:移动端网站第三方弹窗返回后HTTP请求重试与超时控制实现求助

Solution for Angular 11 Retry & Timeout Logic

Got it, let's fix this up for you. Your current code is missing a few key pieces to meet all your requirements—like handling the response.await === true case for retries, adding a global 20-second timeout, and getting the retry count logic right. Here's a complete solution tailored to your Angular 11 needs:

import { of, throwError, timer } from 'rxjs';
import { switchMap, retryWhen, mergeMap, timeout, catchError } from 'rxjs/operators';

// Assume your httpService and SOME_API are defined elsewhere
initiateProcess() {
  const MAX_RETRIES = 5; // Maximum number of retries (total attempts = 1 + 5 = 6)
  const RETRY_DELAY = 3000; // 3-second delay between retries
  const GLOBAL_TIMEOUT = 20000; // 20-second total process timeout

  let retryCount = 0;

  return of(1).pipe(
    // Step 1: Enforce global 20-second timeout for the entire process
    timeout(GLOBAL_TIMEOUT),
    // Step 2: Make the initial API call
    switchMap(() => this.httpService.getFromApi(SOME_API)),
    // Step 3: Check if response requires retry, trigger retry if needed
    switchMap(response => {
      if (response.await === true) {
        // Throw a custom error to signal we need to retry
        return throwError(() => new Error('RETRY_TRIGGERED_BY_RESPONSE'));
      }
      // No retry needed, return the valid response
      return of(response);
    }),
    // Step 4: Handle retries for both API errors and response-triggered retries
    retryWhen(errors =>
      errors.pipe(
        mergeMap(error => {
          retryCount++;
          // Stop retrying if we've hit the maximum retry limit
          if (retryCount > MAX_RETRIES) {
            return throwError(() => new Error('Maximum retry attempts exceeded'));
          }
          // Wait 3 seconds before retrying
          return timer(RETRY_DELAY);
        })
      )
    ),
    // Step 5: Customize error messages for clarity
    catchError(error => {
      if (error.name === 'TimeoutError') {
        return throwError(() => new Error('Process timed out after 20 seconds'));
      }
      return throwError(() => error);
    })
  );
}

Key Improvements & Explanations:

  • Global 20-second Timeout: The timeout(GLOBAL_TIMEOUT) operator ensures the entire process (initial call + all retries) stops immediately if it takes longer than 20 seconds, throwing a clear timeout error.
  • Response-Driven Retries: We added a switchMap to check response.await === true—if this condition is met, we throw an error that triggers the retry logic, which your original code didn't handle.
  • Correct Retry Counting: We track retryCount explicitly, stopping after 5 retries (total of 6 attempts, which matches your requirement of "maximum retry次数为5次").
  • Clean Retry Trigger: Using timer(RETRY_DELAY) instead of delay is a better RxJS practice here—it creates a new cold observable for each retry, ensuring consistent delays.
  • Clear Error Handling: The final catchError differentiates between timeout errors and retry failures, making debugging easier.

Issues in Your Original Code:

  1. Missing Response Retry Logic: Your code only retried on API errors, not when response.await === true.
  2. Incorrect Retry Count: Setting tries=4 meant you only retried 4 times instead of the required 5.
  3. No Global Timeout: There was no mechanism to stop the process if it exceeded 20 seconds.
  4. Suboptimal Retry Trigger: Returning of(error) in mergeMap could lead to unexpected behavior—using timer is more reliable for delayed retries.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 14:24:07