request-context-cache.service.ts 1.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546
  1. import { RequestContext } from '../api';
  2. /**
  3. * @description
  4. * This service is used to cache arbitrary data relative to an ongoing request.
  5. * It does this by using a WeakMap bound to the current RequestContext, so the cached
  6. * data is available for the duration of the request. Once the request completes, the
  7. * cached data will be automatically garbage-collected.
  8. */
  9. export class RequestContextCacheService {
  10. private caches = new WeakMap<RequestContext, Map<any, any>>();
  11. set<T = any>(ctx: RequestContext, key: any, val: T): void {
  12. this.getContextCache(ctx).set(key, val);
  13. }
  14. get<T = any>(ctx: RequestContext, key: any): T | undefined;
  15. get<T>(ctx: RequestContext, key: any, getDefault?: () => T): T;
  16. get<T>(ctx: RequestContext, key: any, getDefault?: () => T): T | Promise<T> | undefined {
  17. const ctxCache = this.getContextCache(ctx);
  18. const result = ctxCache.get(key);
  19. if (result) {
  20. return result;
  21. }
  22. if (getDefault) {
  23. const defaultResultOrPromise = getDefault();
  24. ctxCache.set(key, defaultResultOrPromise);
  25. return defaultResultOrPromise;
  26. } else {
  27. return;
  28. }
  29. }
  30. private getContextCache(ctx: RequestContext): Map<any, any> {
  31. let ctxCache = this.caches.get(ctx);
  32. if (!ctxCache) {
  33. ctxCache = new Map<any, any>();
  34. this.caches.set(ctx, ctxCache);
  35. }
  36. return ctxCache;
  37. }
  38. private isPromise<T>(input: T | Promise<T>): input is Promise<T> {
  39. return typeof (input as any).then === 'function';
  40. }
  41. }