1. 动态调整超时时间
- 基于网络状态:利用浏览器提供的
navigator.connection
API(在支持的浏览器中)获取网络连接类型(如 'wifi', 'cellular' 等)和带宽估计值。例如,如果是 'cellular' 且带宽较低,适当增加超时时间。
if ('connection' in navigator) {
const connection = navigator.connection;
connection.addEventListener('change', () => {
if (connection.effectiveType === '4g') {
// 假设4g网络相对稳定,设置较短超时
this.httpClient.get(url, { timeout: 5000 });
} else if (connection.effectiveType === '2g') {
// 2g网络不稳定,增加超时时间
this.httpClient.get(url, { timeout: 15000 });
}
});
}
- 基于请求历史:记录每次请求的响应时间,对于同一API的后续请求,根据之前响应时间的统计值来动态调整超时时间。例如,通过维护一个请求响应时间的数组,计算平均值和标准差,以平均值加上一定倍数标准差作为新的超时时间。
2. 避免无效重试
- 设置重试策略:对于一些因网络波动导致的请求失败,可以设置重试机制,但要避免无限重试。例如,最多重试3次,每次重试间隔逐渐增加(指数退避算法)。
import { retry, retryWhen, delay } from 'rxjs/operators';
this.httpClient.get(url).pipe(
retryWhen(errors =>
errors.pipe(
delay(1000), // 第一次重试间隔1秒
delay(2000), // 第二次重试间隔2秒
delay(4000), // 第三次重试间隔4秒
take(3) // 最多重试3次
)
)
).subscribe();
- 判断错误类型:并非所有的请求失败都值得重试。例如,400(Bad Request)或401(Unauthorized)错误通常是由于请求本身或认证问题,不应重试。只有网络相关错误(如超时、网络连接中断等)才进行重试。可以通过拦截器判断错误状态码来决定是否重试。
import { Injectable } from '@angular/core';
import {
HttpEvent,
HttpHandler,
HttpInterceptor,
HttpRequest
} from '@angular/common/http';
import { Observable } from 'rxjs';
import { retryWhen, delay, take } from 'rxjs/operators';
@Injectable()
export class RetryInterceptor implements HttpInterceptor {
intercept(
request: HttpRequest<any>,
next: HttpHandler
): Observable<HttpEvent<any>> {
return next.handle(request).pipe(
retryWhen(errors =>
errors.pipe(
delay(1000),
take(3),
filter((error: any) => {
// 只对网络相关错误重试,这里假设网络错误状态码为0
return error.status === 0;
})
)
)
);
}
}
3. 实际场景应用
- 场景:一个移动电商应用,用户在浏览商品列表和下单时会发起HTTP请求。
- 应用动态调整超时时间:用户在移动网络下浏览商品列表,由于移动网络不稳定,设置较长超时时间(如10秒)。当用户切换到稳定的WiFi网络时,缩短超时时间(如5秒),以提高响应速度。
- 应用避免无效重试:在用户下单时,如果因网络波动请求失败,按照指数退避算法最多重试3次。但如果是因为用户填写信息有误导致400错误,不进行重试,直接提示用户修改信息。