The cache function in VUe2

The vue2 version has such a caching function

  /** * 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))
    })
  }
  
Copy the code

The above function has a common scenario, such as an array, where the first letter of each element needs to be capitalized.

const array = ['abc'.'ed'.'abc'.'acd'.'ed'.'fkg'. ] ;Copy the code

Common solutions

Capitalize (capitalize) {capitalize (capitalize) {capitalize (capitalize) {capitalize (capitalize); const capitalizeArray = array.map(capitalize);Copy the code

If we look carefully, we will see that there are many duplicate elements in array. They return the same result. There is no need to duplicate the capitalize execution, and capitalize is a PURE function. Modified as follows

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

Copy the code

The cached result is returned when a duplicate string is encountered. Think about capitalize is a very time consuming task, performance optimization is more than a little bit.

Modify the VUE cache function

The above example is a pure function for caching synchronization tasks. There is a scenario in business development where input box search exists. When the input box triggers an input event, we call the interface to return the query result. For example, I input the keyword of Nuggets and returned the result, and then INPUT nuggets and NBA returned the result. At this time, I deleted NBA and queried nuggets. In fact, we have checked this result before, and if we cache it, we can directly pull the cache without calling the interface.

We implement a memo that caches asynchronous pure functions based on cached

const cachedAsync = function(fn) {
    const cache = Object.create(null);
    return async str => {
        const hit = cache[str];
        if (hit) {
            return hit;
        }
        // Only successful promises are cached, and failures are rerequested
        return (cache[str] = await fn(str));
    };
};
Copy the code

Usage scenarios

const cachedAsyncQueryPrdList = cachedAsync(prdNo= > {
    // Here is a request action that returns a promise
    return queryPrdList({
        prdNo
    });
}); 

<template>
    <el-input v-model="prdNo" @input="handleQueryPrdList" />
    <el-select>
        <el-option v-for="item in prdList" :label="item.label" :value="item.value">
    </el-select>
</template>export default { data() { prdNo: '', prdList: [], }, methods: { handleQueryPrdList() { const { data } cachedAsyncQueryPrdList(this.prdNo); this.prdList = data; }}}Copy the code

If the previous request was successful, the cache will be pulled up and no request will be sent to the server again. Because our memo will only cache successful promises.

To optimize the

For the above scenario, although the el-Input layer already uses compositionEnd and compositionStart events to provide a layer of stabilization, the input event will not be triggered until the text is actually entered on the screen. But this is not enough, if the user input hand speed is very fast, there will be a second to send several requests, increasing the server burden. So this is usually used with the anti – shake function.

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

And then use it with our cachedAsync

const cachedAsyncQueryPrdList = cachedAsync(prdNo= > {
    // Here is an ajax request action that returns a promise
    return queryPrdList({
        prdNo
    });
}); 

<template>
    <el-input v-model="prdNo" @input="debounceQueryPrdListFn" />
    <el-select>
        <el-option v-for="item in prdList" :label="item.label" :value="item.value">
    </el-select>
</template>export default { data() { prdNo: '', prdList: [], debounceQueryPrdListFn: () => {}, }, created() { this.debounceQueryPrdListFn = debounce(this.handleQueryPrdList); }, methods: { handleQueryPrdList() { const { data } cachedAsyncQueryPrdList(this.prdNo); this.prdList = data; }}}Copy the code

FBI WARNING: cachedAsync function, only applicable to PURE functions.