用于AJAX请求的RxJS节流阀

用于AJAX请求的RxJS节流阀,rxjs,Rxjs,我想创建一个函数,将AJAX请求发送到后端。如果这个函数在同一时间被多次调用,那么它不应该向服务器发出许多相同的请求。它只能发出一个请求 例如: doAJAX('http://example-1.com/').subscribe(res => console.log); // must send a request doAJAX('http://example-1.com/').subscribe(res => console.log); // must NOT send a req

我想创建一个函数,将AJAX请求发送到后端。如果这个函数在同一时间被多次调用,那么它不应该向服务器发出许多相同的请求。它只能发出一个请求

例如:

doAJAX('http://example-1.com/').subscribe(res => console.log); // must send a request
doAJAX('http://example-1.com/').subscribe(res => console.log); // must NOT send a request
doAJAX('http://example-2.com/').subscribe(res => console.log); // must send a request, bacause of different URL
window.setTimeout(() => {
    doAJAX('http://example-2.com/').subscribe(res => console.log); // must send a request because too much time has passed since the last request
}, 3000)
所有函数调用都应该返回一个结果,就好像请求是实际发出的一样

我认为出于这个目的,我可以使用RxJS库。 我已经这样做了:

const request$ = new Subject < string > ();

const response$ = request.pipe(
    groupBy((url: string) => url),
    flatMap(group => group.pipe(auditTime(500))), // make a request no more than once every 500 msec
    map((url: string) => [
        url,
        from(fetch(url))
    ]),
    share()
);

const doAJAX = (url: string): Observable <any> {
    return new Observable(observe => {
        response$
            .pipe(
                filter(result => result[0] === url),
                first(),
                flatMap(result => result[1])
            )
            .subscribe(
                (response: any) => {
                    observe.next(response);
                    observe.complete();
                },
                err => {
                    observe.error(err);
                }
            );
        request$.next(url);
    });
}
const request$=新主题();
const response$=request.pipe(
groupBy((url:string)=>url),
flatMap(group=>group.pipe(auditTime(500)),//每500毫秒发出一次请求
映射((url:string)=>[
网址,
从(获取(url))
]),
股份()
);
constdoajax=(url:string):可观察{
返回新的可观察对象(观察=>{
回应$
.烟斗(
过滤器(结果=>结果[0]==url),
第一个(),
flatMap(结果=>结果[1])
)
.订阅(
(答复:任何)=>{
观察。下一步(回答);
观察。完成();
},
错误=>{
观察错误(err);
}
);
请求$.next(url);
});
}
我创建
请求$
主题和
响应$
可观察
doAjax
函数订阅
response$
并将URL字符串发送到
request$
主题。在
request$
流中还有
groupBy
auditTime
操作符。和
doAJAX
函数中的过滤器运算符


这个代码可以工作,但我认为它非常困难。有没有办法使这项任务更容易?也许RXJS调度器或不使用RXJS库在所有

< P>,因为这整个点是为了记住HTTP结果和延迟重复调用,您可以考虑自己的记忆化。例如:

const memoise = (func) => {
  let cache: { [key:string]: Observable<any> } = {};

  return (...args): Observable<any> => {
    const cacheKey = JSON.stringify(args)
    cache[cacheKey] = cache[cacheKey] || func(...args).pipe(share());

    return cache[cacheKey].pipe(
      tap(() => timer(1000).subscribe(() => delete cache[cacheKey]))
    );
  }
}
const memoise=(func)=>{

let cache:{[key:string]:Observable

非常感谢。它确实帮助了我。一个小修复,在您的示例中,删除缓存[cacheKey]从未被调用(我不知道为什么在您的示例中memoize有效,可能是stackblitz中的服务人员)这里修复了演示:是的,它有这样的问题。因为
点击(()=>定时器(1000)。管道(
只是创建了新的可观察的新功能。而
订阅
就像你做的那样是可以的-
计时器(1000)
自行完成,因此不需要取消订阅,如果没有更深层的逻辑,我同意订阅在这里是可以的(与合并
计时器()
到主流相比,这通常是一种首选方式)