角度缓存并行请求

时间:2018-05-24 08:56:52

标签: angular caching rxjs

我已经定义了一个拦截器来缓存API响应:

    if (req.method == 'GET') {
        // return cached object if exists
        const cachedResponse = this.cache.get(req) || null;
        if (cachedResponse) {
            return Observable.of(cachedResponse);
        }

        // call api and cache result if doesn't exist
        return next.handle(req).do(event => {
            if (event instanceof HttpResponse) {
                this.cache.put(req, event)
            }
        });
    }
    return next.handle(req);

这里缺少的是,如果请求处于待处理状态,请不要处理该请求,但要等待请求在缓存上准备好并返回它。

使这种逻辑适应这个问题的最佳方法是什么?

3 个答案:

答案 0 :(得分:0)

你的意思是你的do()函数,并行请求会遇到什么问题?比如,2个请求使用相同的url,那么这两个请求都将被发送到服务器并放入缓存?

这个怎么样?不要将HttpResponse放在缓存中,而是放置Observable对象。像这样:

    if (req.method == 'GET') {
    // return cached object if exists
    const cachedResponse = this.cache.get(req) || null;
    if (cachedResponse) {
        return cachedResponse); // it is Observable, even same req in the sam,e time, the second will get a Observable data.
    }

    // call api and cache result if doesn't exist
    const result = next.handle(req);
    this.cache.put(req, result)
    result.do(event => {
        if (event !instanceof HttpResponse) {
            this.cache.remove(req) // if it is error, maybe remove?
        }
    return result;
    });
}
return next.handle(req);

答案 1 :(得分:0)

我已经解决了使用缓存dict和队列dict与共享运算符的问题,如下所示:

if (req.method == 'GET') {

    // return cached object if exists
    const cachedResponse = this.cache.get(req) || null;
    if (cachedResponse) {
        return Observable.of(cachedResponse);
    }

    const pendingResponse = this.queue.get(req) || null;
    if (pendingResponse) {
        return pendingResponse;
    }
    // call api and cache result if doesn't exist
    var obs = next.handle(req).do(event => {
        if (event instanceof HttpResponse) {
            this.cache.put(req, event)
            this.queue.clear(req.urlWithParams)
        }
    }).share();
    this.queue.put(req, obs)
    return obs
}
return next.handle(req);

答案 2 :(得分:0)

如果请求处于待处理状态,您可以尝试使用shareReplay-同一请求将被重用,如果请求已完成-将发出最后一个值。

if (req.method == 'GET') {

  if (!this.cache.get(req)) {
      const cached = next.handle(req).shareReplay();
      this.cache.put(req, cached);
  }

  return this.cache.get(req);
}
return next.handle(req);