axiosパッケージ-動的ローディング、データキャッシング

最先端

インターネットで多くのaxiosパッケージを読んだ後、それらは特に完璧ではないと感じています。したがって、次の機能を含む比較的完全なパッケージを作成する予定です(まだすべてが完了しているわけではなく、継続的に更新されます)。

  1. ファイルをアップロードおよびダウンロードするときのヘッダー設定
  2. エラー対応統一処理
  3. APIを動的にロードします(完了)
  4. データキャッシュ(完了)、キャッシュのクリア(完了)、キャッシュレベル(完了)、キャッシュの最大数(完了)
  5. 繰り返されるリクエストをインターセプトし(完了)、ページがジャンプしたらリクエストをキャンセルします
  6. トークンを更新

今のところ考えられることはこれだけです。他にアイデアがあれば、私にメッセージを残してください。

1.動的ローディング

 リクエストするたびに対応するファイルをインポートするのは面倒です。

// 引入
import { add } from "@/api/tool/code";
// 在方法中
add()

これの利点は、最初に多数のAPIをロードする必要がないことです。欠点は、特に多くのインターフェイスに導入する必要があるいくつかの一般的なインターフェイスでは、各ページを手動でインポートする必要があることです。

Proxyオブジェクトを使用すると、APIの自動ロードを実現できます。もちろん、Proxyは、オブジェクトメソッドにアクセスするときに、いくつかのパブリックメソッドを使用して自動的にロードすることもできます。

let api = {};
api = new Proxy(api, {
    // apiName是访问api下的对象名称也作为文件名称和文件里所有api的名字,在数据缓存中有相关处理
    get(target, apiName) {
        if (target[key] === undefined) { //在访问api的属性是判断是否有这个属性没有的话就按照名字和固定的路径去加载文件,然后挂载上去,最后返回。
            console.log(target, apiName);
            //加载路径可以根据自己的api放置位置和规则修改
            let obj = require('./api/' + apiName + '.js').default;
            target[apiName] = {};
            for (let item in obj) {
                target[key][item] = (data) => {
                    return request(obj[item](data), apiName);
                }
            }
        }
        return target[key];
    }
})

export default api;  //这里导出,最后挂载到全局

2.データのキャッシュと繰り返されるリクエストの傍受

const service = axios.create({
    // 设置请求超时时间
    baseURL: '/api',
    timeout: 20000,
    headers: {
        'content-type': 'application/json', // 设置请求体类型
        /*
        常用的请求格式有:
            'application/json': 发送JSON对象
            'multipart/form-data': 需要文件上传时,就使用该格式
        
        根据后台需求发送其他需要放在header里面数据,例如:
            'Authorization': 'Basic ****', //登录验证
        */
    },
    // 默认情况下,后台状态码不返回200的话,是不会收到返回数据的,可以根据需要设置后台返回状态码的区间
    validateStatus: function(status) {
        return status >= 200 && status <= 500;
    },
    // 请求时是否携带cookie信息
    withCredentials: true,
})

// 定义最大缓存数量
const MAXCACHE = 5;
// 定义缓存对象
let caChe = {
    list: [],
    // 每个请求都有缓存级别,数字越小缓存级别越高
    add(data) {
        // 找到相同或小于当前级别的缓存的下标
        let index = this.list.findIndex(item => {
            return item.level ? data.level < item.level : true;
        })
        // 如果没有找到就插入到最前面,如果有就插入到这个缓存的前面
        if (index <= 0) {
            this.list.unshift(data);
        } else {
            this.list.splice(index, 0, data);
        }
        // 如果达到最大缓存数量,删除最后一个
        if (this.list.length > MAXCACHE) {
            this.list.pop();
        }
    },
    // 找到这个key的缓存
    find(key) {
        return this.list.find(item => {
            return key === item.key;
        })
    },
    // 根据api名称删除缓存
    deleteApiName(apiName) {
        this.list = this.list.filter(item => {
            return item.apiName !== apiName;
        })
    }
};
// 定义一个正在请求的列表,用来防止重复请求
let request_list = {};

let request = (params, apiName) => {
    // 使用哈希MD5函数将 url、params、data 的数据组成一个key,这里使用HmacMd5就是不想这个key太长
    let key = params.url + HmacMd5(JSON.stringify(params.params) + JSON.stringify(params.data)).toString();
    console.log(key);
    //如果request_list[key]有值则是判断为重复请求
    if (request_list[key]) {
        console.log('接口正在请求,等待返回');

        return Promise.reject({
            code: 301,
            msg: '请求中,请稍等',
        });
    // 判断缓存中是否有,有的话直接返回
    } else if (caChe.find(key) !== undefined) {
        console.log('有缓存,直接返回数据');
        return Promise.resolve(caChe.find(key).response_data);
    } else {
        return new Promise((resolve, reject) => {
            console.log('没有缓存,发起请求');
            
            // 添加key标识接口正在请求
            request_list[key] = { apiName };
            
            service(params).then(res => {

                resolve(res.data);
                
                // 如果不是get请求就删除对应apiName的缓存,例如:
                // 请求用户列表后缓存了返回数据,当我添加或修改了某一个用户后,在获取就应该请求数据而不是拿缓存中的数据;我这里的apiName为文件名
                if (params.method !== 'get') {
                    caChe.deleteApiName(apiName);
                } else if (params.isCache || params.isCache === undefined) {
                    // 判断接口是否需要缓存,接口默认为缓存
                    caChe.add({
                        response_data: res.data,
                        key,
                        apiName,
                        level: params.level,
                    })
                }
            }).catch(err => {
                reject(err.data);
            }).finally(() => {
                // 不管成功与否都删除正在请求列表中对应的key,方便下次请求
                delete request_list[key];
            })
        })
    }
}

3.APIパッケージファイル



let user = {
    get: ({ current, size }) => {
        return {
            url: '/user',
            method: 'get',
            isCache: true, // 是否缓存,不写默认为缓存
            level: 0, // 缓存级别
            params: { current, size }
        }
    },
    post: (data) => {
        return {
            url: '/user',
            method: 'post',
            data: {
                name: data.name,
                age: data.age
            }
        }
    },
    put: ({ id, name, age }) => {
        return {
            url: '/user',
            method: 'put',
            data: { id, name, age },
        }
    },
    delete: ({ id }) => {
        return {
            url: '/user',
            method: 'delete',
            params: { id: id },
        }
    }
}

export default user;

おすすめ

転載: blog.csdn.net/qq_18676843/article/details/122983122