最近发现在开发环境出现了缓存溢出的报错的问题,所以我决定对缓存进行一次封装,当发现缓存缓存写入或者读取失败时,可以自定义后续的处理方式。

关键点在于,如何同时适配storage的setItem和点调用两种形式。

代码参考

/**
 * 缓存服务
 */
const storageConfig = {
    LOCALSTORAGE: 'localStorage',
    SESSIONSTORAGE: 'sessionStorage'
};

const isQuotaExceeded = (e) => {
    let quotaExceeded = false;
    if (e) {
        if (e.code) {
            switch (e.code) {
                case 22:
                    quotaExceeded = true;
                    break;
                case 1014:
                    // Firefox
                    if (e.name === 'NS_ERROR_DOM_QUOTA_REACHED') {
                        quotaExceeded = true;
                    }
                    break;
                default:
            }
        }
        else if (e.number === -2147024882) {
            // IE8
            quotaExceeded = true;
        }
    }
    return quotaExceeded;
};

const setStorage = (storage, key, value) => {
    if (window[storage]) {
        try {
            window[storage].setItem(key, value);
        }
        catch (e) {
            // if (e.name === 'QUOTA_EXCEEDED_ERR' || e.name === 'NS_ERROR_DOM_QUOTA_REACHED') {
            //     // 存储超限
            // } else {
            //     // 保存失败
            // }
            // 兼容性写法
            if (isQuotaExceeded(e)) {
                // 存储超限
            }
            else {
                // 保存失败
            }
            return false;
        }
    }
    return true;
};

/* 关键代码 */
const storageProxy = (storageName) =>
    new Proxy(window[storageName], {
        get: (target, property, receiver) => {
            switch (property) {
                case 'setItem':
                    return (...args) => setStorage(storageName, args[0], args[1]);
                case 'getItem':
                case 'key':
                case 'removeItem':
                case 'clear':
                    return (...args) => target[property](...args);
                default:
                    return Reflect.get(target, property, receiver);
            }
        },
        set: (target, property, value, receiver) => {
            return setStorage(storageName, property, value);
        },
    });

const LocalStorage = storageProxy(storageConfig.LOCALSTORAGE);
const SessionStorage = storageProxy(storageConfig.SESSIONSTORAGE);

export {
    LocalStorage,
    SessionStorage,
};

参考链接

  1. Proxy 和 Reflect.