【发布时间】:2018-11-16 06:04:20
【问题描述】:
我有一个基于参数执行 http 请求的函数。我想添加某种“去抖动”功能。因此,如果函数在设定的时间窗口内被多次调用,我想将参数组合到一个请求中,而不是发出多个请求。
我想通过 Observables 和 Angular 来实现这一点。这听起来并不复杂,但是我无法让它运行,也许我错过了一些东西。
现在让我们跳过单个请求中的组合,因为这可以通过聚合去抖动或 Oberservable.buffer 来完成。我无法组合单个 Observables。
这是我迄今为止尝试过的。
我尝试使用主题,因为这似乎是本案例的正确对象 (https://stackblitz.com/edit/angular-hcn41v?file=src%2Fapp%2Fapp.component.ts)。
constructor(private http: HttpClient) {
this.makeRequest('1').subscribe(x => console.log(x))
this.makeRequest('2').subscribe(console.log)
setTimeout(() => {
this.makeRequest('3').subscribe(console.log)
}, 1000)
}
private makeRequest(id: string) {
this.observable = this.observable.pipe(
merge(Observable.of(id).pipe(delay(1)))
)
return this.aggregateDebounce(this.observable)
}
private getUrl(value) {
console.log('getUrl Call', value);
return 'https://jsonplaceholder.typicode.com/posts/1';
}
private aggregateDebounce(ob$) {
const shared$ = ob$.publishReplay(1).refCount()
return shared$.buffer(shared$.debounceTime(75))
}
我希望每个函数调用都有一个“getUrl Call”日志和一个结果日志。但是,如果我向 this.makeRequest() 添加超过 1 个调用,我只会得到结果,结果也很奇怪。也总是返回所有以前的值。我想我不完全理解 Subject 在这种情况下是如何工作的。
另一种方法(取自这里RXJS: Aggregated debounce)是创建某种聚合去抖动(https://stackblitz.com/edit/angular-mx232d?file=src/app/app.component.ts)
constructor(private http: HttpClient) {
this.makeRequest('1').subscribe(x => console.log(x))
this.makeRequest('2').subscribe(console.log)
setTimeout(() => {
this.makeRequest('3').subscribe(console.log)
}, 1000)
}
private makeRequest(id: string) {
this.observable = this.observable.pipe(
merge(Observable.of(id).pipe(delay(1)))
)
return this.aggregateDebounce(this.observable)
}
private getUrl(value) {
console.log('getUrl Call', value);
return 'https://jsonplaceholder.typicode.com/posts/1';
}
private aggregateDebounce(ob$) {
const shared$ = ob$.publishReplay(1).refCount()
return shared$.buffer(shared$.debounceTime(75))
}
在这种情况下,我遇到了问题,我也得到了所有以前的值。
理论上(至少对我而言)这两种变体听起来都是合理的,但我似乎遗漏了一些东西。任何朝着正确方向的眨眼都会受到高度赞赏。
编辑:
根据要求,我添加了最终的现实世界目标。
想象一个从 API 请求信息的服务。在 50-75 毫秒内,您调用具有特定 ID 的服务。我想将这些 id 组合到一个请求而不是执行 3 个请求。如果 100 毫秒后再次调用该服务,则会完成一个新请求
【问题讨论】:
-
你的意思是如果你拿到了之前执行过的参数,你就不想再执行一次了吧?多久不想重新运行?
-
完全正确。我添加了一个示例以进一步说明。 50-75ms
-
我已经更新了我的答案以包含一个可能的解决方案。
-
非常感谢。如果我能把它应用到我的例子中,我会看看。
标签: javascript angular typescript rxjs observable