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()
    
    
  • 相关阅读:
    Spring MVC Ajax 嵌套表单数据的提交
    Spring MVC 过滤静态资源访问
    Spring MVC 页面跳转时传递参数
    IDEA Maven 三层架构 2、运行 springMVC
    IDEA Maven 三层架构 1、基本的Archetype 搭建
    EasyUI DataGrid 基于 Ajax 自定义取值(loadData)
    Spring MVC Ajax 复杂参数的批量传递
    Mybatis Sql片段的应用
    在 Tomcat 8 部署多端口项目
    自动升级的设计思路与实现
  • 原文地址:https://www.cnblogs.com/mapleChain/p/15802385.html
Copyright © 2011-2022 走看看