如何巧用Vue缓存函数浅析

编辑: admin 分类: javascript 发布时间: 2021-11-17 来源:互联网
目录
  • vue2中的缓存函数
  • 改造vue缓存函数
  • 优化
  • 总结

vue2中的缓存函数

vue2版本中有这么一个缓存函数

  /**
   * Create a cached version of a pure function.
   */
  function cached (fn) {
    var cache = Object.create(null);
    return (function cachedFn (str) {
      var hit = cache[str];
      return hit || (cache[str] = fn(str))
    })
  }
  

上面这个函数存在一个常用场景,比如存在一个数组,需要把每个元素的首字母转为大写。

const array = ['abc', 'ed', 'abc', 'acd', 'ed', 'fkg', ...];

常用的解决方法

// 定一个capitalize函数
function capitalize (str) {
    return str.charAt(0).toUpperCase() + str.slice(1)
 };
  
 const capitalizeArray = array.map(capitalize);

细心的我们会发现array中存在不少重复的元素, 他们返回的结果一样的,实际不需要重复计算执行capitalize,而且capitalize是一个PURE函数,此时我们可以利用上面的cached做一个备忘录的功能。

改造如下

function capitalize (str) {
    return str.charAt(0).toUpperCase() + str.slice(1)
 };
  
const capitalizeArray = array.map(cached(capitalize));

当遇到重复字符串的时候会直接返回缓存的结果。想想capitalize是一个十分耗时的任务,性能优化不止一点点。

改造vue缓存函数

上面的举例是缓存同步任务的纯函数,在业务开发中存在这么一个场景,输入框搜索。当输入框触发input事件的时候,我们都会调用接口返回查询结果。比如我输入了掘金关键字返回了结果,然后又输入掘金NBA返回了结果,此时我删掉了NBA,又查询掘金, 实际上这个结果我们之前查过,如果缓存起来直接拉缓存即可,不用再去调用接口。

我们基于cached实现一个缓存异步纯函数的备忘录

const cachedAsync = function(fn) {
    const cache = Object.create(null);
    return async str => {
        const hit = cache[str];
        if (hit) {
            return hit;
        }
        // 只缓存成功的Promise, 失败直接重新请求
        return (cache[str] = await fn(str));
    };
};

使用场景

const cachedAsyncQueryPrdList = cachedAsync(prdNo => {
    // 下面是一个请求的操作,返回一个promise
    return queryPrdList({
        prdNo
    });
}); 

<template>
    <el-input v-model="prdNo" placeholder="请输入产品编码" @input="handleQueryPrdList" />
    <el-select>
        <el-option v-for="item in prdList" :label="item.label" :value="item.value">
    </el-select>
</template>
<script>
export default {
    data() {
        prdNo: '',
        prdList: [],
    },
    methods: {
        async handleQueryPrdList() {
            const { data } = await cachedAsyncQueryPrdList(this.prdNo);
            this.prdList = data;
        }
    }
}
</script>

上面实现了,当输入相同的关键字,如果之前请求是成功的,直接拉起缓存,不会重新向服务器发起请求。因为我们的备忘录只会缓存成功的promise。

优化

针对上面的场景,美国cn2站群服务器http://www.558idc.com/mggfzq.html虽然el-input底层已经使用compositionEnd和compositionStart事件来做一层防抖,只有文字真正输入到屏幕上才会去触发input事件。但是这是不够,如果用户输入手速很快,会出现一秒发几次请求的情况,增加了服务器负担。因此这种一般会搭配防抖函数使用。

防抖函数

const debounce = (fn, ms = 300) => {
    let timeoutId;
    return function(...args) {
        clearTimeout(timeoutId);
        timeoutId = setTimeout(() => fn.apply(this, args), ms);
    };
};

然后搭配我们的cachedAsync使用

const cachedAsyncQueryPrdList = cachedAsync(prdNo => {
    // 下面是一个ajax请求的操作,返回一个promise
    return queryPrdList({
        prdNo
    });
}); 

<template>
    <el-input v-model="prdNo" placeholder="请输入产品编码"  @input="debounceQueryPrdListFn" />
    <el-select>
        <el-option v-for="item in prdList" :label="item.label" :value="item.value">
    </el-select>
</template>
<script>
const noop = () => {};
export default {
    data() {
        prdNo: '',
        prdList: [],
        debounceQueryPrdListFn: noop,
    },
    created() {
        this.debounceQueryPrdListFn = debounce(this.handleQueryPrdList);
    },
    methods: {
        async handleQueryPrdList() {
            const { data } = await cachedAsyncQueryPrdList(this.prdNo);
            this.prdList = data;
        }
    }
}
</script>

FBI WARNING:  >>> cachedAsync函数,只适用于PURE函数。

这个实现已经在生产环境稳定使用,大家可以放心食用。

总结

到此这篇关于如何巧用Vue缓存函数的文章就介绍到这了,更多相关巧用Vue缓存函数内容请搜索hwidc以前的文章或继续浏览下面的相关文章希望大家以后多多支持hwidc!