zoukankan      html  css  js  c++  java
  • 函数缓存

    一般可用于优化本地请求多次

    // util.ts
    import addSeconds from 'date-fns/add_seconds';
    import getTime from 'date-fns/get_time';
    import request from './ajax'; // 自己封装好的request
    
    /**
     * 创建一个会缓存 func 结果的函数。 如果提供了 resolver ,就用 resolver 的返回值作为 key 缓存函数的结果。
     *  默认情况下用第一个参数作为缓存的 key。 func 在调用时 this 会绑定在缓存函数上。相比 lodash-es 库,增加了异步函数的支持。
     * @memberof module:shared
     * @param {function} fn 需要缓存化的函数
     * @param {function} opt 配置项 resolver: 生成 key , expire: 过期时间,以秒为单位
     * @return {function} 包装后的函数
     * @example
     *
     * const obj = { a: 1, b: 2 }
     * const foo = (obj) => Object.values(obj)
     * const bar = memorize(foo)
     * bar(obj)
     * // [1, 2]
     * obj.a = 10
     * bar(obj)
     * // [1, 2]
     */
    
    function isPromise(value: any): boolean {
      return typeof value === 'object' && value !== null && typeof value.then === 'function';
    }
    
    export interface IMemorizeOptions {
      resolver?: (...value: any[]) => NonNullable<any>;
      expire: number;
    }
    
    export function memorize(
      fn: (...rest: any[]) => any,
      opt: IMemorizeOptions = {
        expire: 60
      }
    ) {
      const cache = new Map();
      const { resolver: hash, expire } = opt;
    
      function setExpire(time: number): number | null {
        return typeof time === 'number' ? getTime(addSeconds(Date.now(), time)) : null;
      }
    
      /* eslint-disable no-nested-ternary */
      function memoized(this: any, ...params: any[]) {
        const key = typeof hash === 'function' ? hash(...params) : params[0];
        const {
          expire: curExpire,
          value: memoizedValue,
          shouldReturnPromise
        }: {
          expire?: number;
          value?: any;
          shouldReturnPromise?: boolean;
        } = cache.get(key) || {};
    
        // 过期数据
        if (typeof curExpire === 'number' && Date.now() > curExpire) {
          cache.delete(key);
        }
    
        if (cache.has(key)) {
          return shouldReturnPromise ? Promise.resolve(memoizedValue) : memoizedValue;
        }
    
        const res = fn.apply(this, params);
    
        if (isPromise(res)) {
          return res.then(
            (value: any) => {
              cache.set(key, {
                value,
                expire: setExpire(expire),
                shouldReturnPromise: true
              });
              return value;
            },
            (err: Error) => Promise.reject(err)
          );
        }
        cache.set(key, {
          value: res,
          expire: setExpire(expire)
        });
        return res;
      }
      memoized.cache = cache;
      return memoized;
    }
    
    export function requestWithCache(options?: IMemorizeOptions) {
      return memorize(request, options);
    }
    
    export default requestWithCache;
    
    
    // 使用
    
    function memoReq() {
      return requestWithCache({
        resolver: (url: string, params?: any) => `${url}_${JSON.stringify(params)}`,
        expire: 60 * 10
      });
    }
    
    const cacheReq = memoReq();
    // apply:
    cacheReq('/v1/xxx.api').then().catch()
    
    
  • 相关阅读:
    ReentrantReadWriteLock源码探究
    ReentrantLock源码探究
    CyclicBarrier源码探究 (JDK 1.8)
    ThreadLocal源码探究 (JDK 1.8)
    CountDownLatch源码探究 (JDK 1.8)
    ConcurrentHashMap源码探究 (JDK 1.8)
    备忘录模式
    variable precision SWAR算法
    建造者模式
    Spring MVC 解决乱码
  • 原文地址:https://www.cnblogs.com/mapleChain/p/15802385.html
Copyright © 2011-2022 走看看