Skip to main content
Tweeted twitter.com/StackCodeReview/status/1408892862851424257
deleted 108 characters in body; edited tags; edited title
Source Link
Jamal
  • 34.9k
  • 13
  • 133
  • 237

rxjs: caching Caching different http-requests

There have been multiple discussions on caching http-requestshttp-requests with rxjs, inRXJS. In this question/proposal I want to propose a custom rxjs-operator (non-pure) to provide caching:

const cacheHttp = (cacheKey: string, cacheStorage: any) => (source: Observable<any>) => {
  if (!cacheStorage[cacheKey]) {
    cacheStorage[cacheKey] = source.pipe(
      shareReplay(1)
    );
  }
  return cacheStorage[cacheKey];
};

This operator is not pure, as it modifies one of its arguments (cacheStoragecacheStorage).

This operator could be used like this:

public cachedItems = {};

public getDataForItem$(itemId: string) {
    return this.http.get('/item/' + itemId).pipe(
        cacheHttp(itemId, this.cachedItems),
        shareReplay(1)
    );
}

The client could then call this multiple times without causing superfluous http-requestshttp-requests:

// the following two subscriptions cause http-requests
this.itemService.getDataForItem('firstItem').subscribe((val) => console.log(val));
this.itemService.getDataForItem('secondItem').subscribe((val) => console.log(val));

// all further subscriptions would not cause any additional http-requests
this.itemService.getDataForItem('firstItem').subscribe((val) => console.log(val));
this.itemService.getDataForItem('secondItem').subscribe((val) => console.log(val));
this.itemService.getDataForItem('firstItem').subscribe((val) => console.log(val));
this.itemService.getDataForItem('secondItem').subscribe((val) => console.log(val));

// this subscription would again cause an http-request:
this.itemService.getDataForItem('thirdItem').subscribe((val) => console.log(val));

Now my questions: Is Is this an acceptable approach to solving the "cache-for-different-requests-problem"? Is there possibly a memory-leak or are there any leaked subscriptions? Is it ok to have side-effects on a provided argument?

Any comments or hints on problems with this custom-operator are very welcome!

rxjs: caching different http-requests

There have been multiple discussions on caching http-requests with rxjs, in this question/proposal I want to propose a custom rxjs-operator (non-pure) to provide caching:

const cacheHttp = (cacheKey: string, cacheStorage: any) => (source: Observable<any>) => {
  if (!cacheStorage[cacheKey]) {
    cacheStorage[cacheKey] = source.pipe(
      shareReplay(1)
    );
  }
  return cacheStorage[cacheKey];
};

This operator is not pure, as it modifies one of its arguments (cacheStorage).

This operator could be used like this:

public cachedItems = {};

public getDataForItem$(itemId: string) {
    return this.http.get('/item/' + itemId).pipe(
        cacheHttp(itemId, this.cachedItems),
        shareReplay(1)
    );
}

The client could then call this multiple times without causing superfluous http-requests:

// the following two subscriptions cause http-requests
this.itemService.getDataForItem('firstItem').subscribe((val) => console.log(val));
this.itemService.getDataForItem('secondItem').subscribe((val) => console.log(val));

// all further subscriptions would not cause any additional http-requests
this.itemService.getDataForItem('firstItem').subscribe((val) => console.log(val));
this.itemService.getDataForItem('secondItem').subscribe((val) => console.log(val));
this.itemService.getDataForItem('firstItem').subscribe((val) => console.log(val));
this.itemService.getDataForItem('secondItem').subscribe((val) => console.log(val));

// this subscription would again cause an http-request:
this.itemService.getDataForItem('thirdItem').subscribe((val) => console.log(val));

Now my questions: Is this an acceptable approach to solving the "cache-for-different-requests-problem"? Is there possibly a memory-leak or are there any leaked subscriptions? Is it ok to have side-effects on a provided argument?

Any comments or hints on problems with this custom-operator are very welcome!

Caching different http-requests

There have been multiple discussions on caching http-requests with RXJS. In this question/proposal I want to propose a custom rxjs-operator (non-pure) to provide caching:

const cacheHttp = (cacheKey: string, cacheStorage: any) => (source: Observable<any>) => {
  if (!cacheStorage[cacheKey]) {
    cacheStorage[cacheKey] = source.pipe(
      shareReplay(1)
    );
  }
  return cacheStorage[cacheKey];
};

This operator is not pure, as it modifies one of its arguments (cacheStorage).

This operator could be used like this:

public cachedItems = {};

public getDataForItem$(itemId: string) {
    return this.http.get('/item/' + itemId).pipe(
        cacheHttp(itemId, this.cachedItems),
        shareReplay(1)
    );
}

The client could then call this multiple times without causing superfluous http-requests:

// the following two subscriptions cause http-requests
this.itemService.getDataForItem('firstItem').subscribe((val) => console.log(val));
this.itemService.getDataForItem('secondItem').subscribe((val) => console.log(val));

// all further subscriptions would not cause any additional http-requests
this.itemService.getDataForItem('firstItem').subscribe((val) => console.log(val));
this.itemService.getDataForItem('secondItem').subscribe((val) => console.log(val));
this.itemService.getDataForItem('firstItem').subscribe((val) => console.log(val));
this.itemService.getDataForItem('secondItem').subscribe((val) => console.log(val));

// this subscription would again cause an http-request:
this.itemService.getDataForItem('thirdItem').subscribe((val) => console.log(val));

Is this an acceptable approach to solving the "cache-for-different-requests-problem"? Is there possibly a memory-leak or are there any leaked subscriptions? Is it ok to have side-effects on a provided argument?

edited tags
Link
200_success
  • 144.2k
  • 22
  • 188
  • 473
Source Link

rxjs: caching different http-requests

There have been multiple discussions on caching http-requests with rxjs, in this question/proposal I want to propose a custom rxjs-operator (non-pure) to provide caching:

const cacheHttp = (cacheKey: string, cacheStorage: any) => (source: Observable<any>) => {
  if (!cacheStorage[cacheKey]) {
    cacheStorage[cacheKey] = source.pipe(
      shareReplay(1)
    );
  }
  return cacheStorage[cacheKey];
};

This operator is not pure, as it modifies one of its arguments (cacheStorage).

This operator could be used like this:

public cachedItems = {};

public getDataForItem$(itemId: string) {
    return this.http.get('/item/' + itemId).pipe(
        cacheHttp(itemId, this.cachedItems),
        shareReplay(1)
    );
}

The client could then call this multiple times without causing superfluous http-requests:

// the following two subscriptions cause http-requests
this.itemService.getDataForItem('firstItem').subscribe((val) => console.log(val));
this.itemService.getDataForItem('secondItem').subscribe((val) => console.log(val));

// all further subscriptions would not cause any additional http-requests
this.itemService.getDataForItem('firstItem').subscribe((val) => console.log(val));
this.itemService.getDataForItem('secondItem').subscribe((val) => console.log(val));
this.itemService.getDataForItem('firstItem').subscribe((val) => console.log(val));
this.itemService.getDataForItem('secondItem').subscribe((val) => console.log(val));

// this subscription would again cause an http-request:
this.itemService.getDataForItem('thirdItem').subscribe((val) => console.log(val));

Now my questions: Is this an acceptable approach to solving the "cache-for-different-requests-problem"? Is there possibly a memory-leak or are there any leaked subscriptions? Is it ok to have side-effects on a provided argument?

Any comments or hints on problems with this custom-operator are very welcome!