Angular中请求参数不同时如何实现接口请求节流?
问题根因
你当前节流逻辑不生效的核心原因是:throttleTime 是作用在单个Observable实例上的操作符,你每次调用getProductHistory都会返回一个全新的Observable,三个请求对应三个独立的节流逻辑,互相之间没有关联,自然不会触发限流效果。
另外你这里的场景是请求排队限流(需要保证所有请求都被发送,只是控制发送速率),直接用throttleTime也不符合需求,因为throttleTime会直接丢弃窗口期内的多余事件,会导致部分请求丢失。
解决方案
核心思路是把所有请求统一放到同一个队列中管理,全局控制请求发送速率,所有请求按顺序间隔100ms发送,刚好满足每秒最多10次的限制。
只需要改造basic-service.ts即可,上层业务和组件代码无需修改:
// basic-service.ts import { Injectable } from '@angular/core'; import { HttpClient } from '@angular/common/http'; import { Observable, Subject, Subscriber, EMPTY, timer, concatMap, mergeMap, tap, catchError } from 'rxjs'; import { ProductHistory } from './your-type-path'; // 替换为你实际的类型定义路径 @Injectable({ providedIn: 'root' }) export class ApiService { throttle = 100 // 单请求间隔100毫秒,对应每秒最多10次请求 // 统一的请求队列,存储请求参数和对应的观察者 private requestQueue = new Subject<{ start_time: string, observer: Subscriber<ProductHistory> }>(); constructor(private http: HttpClient) { // 初始化队列消费逻辑 this.requestQueue.pipe( // 按队列顺序处理请求,每个请求间隔100ms concatMap(req => timer(this.throttle).pipe( // 发起实际请求 mergeMap(() => this.http.get<ProductHistory>(`https://test.com?start=${req.start_time}`)), // 把请求结果返回给对应调用方 tap(res => { req.observer.next(res); req.observer.complete(); }), // 错误处理,不影响队列后续请求 catchError(err => { req.observer.error(err); return EMPTY; }) )) ).subscribe(); } getProductHistory(start_time: string): Observable<ProductHistory> { // 把请求推入队列,返回对应观察者的Observable return new Observable(sub => { this.requestQueue.next({ start_time, observer: sub }); }); } }
小提示:你原代码中请求URL拼接用了
&作为参数起始符,正常第一个参数前应该用?,上面代码已经做了修正。
上述代码中用concatMap保证队列请求按顺序处理,配合timer(100)严格控制请求间隔,所有请求都会按调用顺序发送,不会丢失,同时完全符合第三方接口的限流规则。
内容的提问来源于stack exchange,提问作者moondc
相关产品推荐
相关产品推荐

