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
switchMapto checkresponse.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
retryCountexplicitly, stopping after 5 retries (total of 6 attempts, which matches your requirement of "maximum retry次数为5次"). - Clean Retry Trigger: Using
timer(RETRY_DELAY)instead ofdelayis a better RxJS practice here—it creates a new cold observable for each retry, ensuring consistent delays. - Clear Error Handling: The final
catchErrordifferentiates between timeout errors and retry failures, making debugging easier.
Issues in Your Original Code:
- Missing Response Retry Logic: Your code only retried on API errors, not when
response.await === true. - Incorrect Retry Count: Setting
tries=4meant you only retried 4 times instead of the required 5. - No Global Timeout: There was no mechanism to stop the process if it exceeded 20 seconds.
- Suboptimal Retry Trigger: Returning
of(error)inmergeMapcould lead to unexpected behavior—usingtimeris more reliable for delayed retries.
内容的提问来源于stack exchange,提问作者Naman Jain
相关产品推荐
相关产品推荐

