npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

axios-cache

v1.2.0

Published

基于axios库封装的集中管理异步请求配置的模块

Downloads

16

Readme

axios-cache

基于axios库封装的集中管理异步请求配置的模块。根据业务需求及开发习惯,参考NEJ的cache使用方式,在保持axios原有配置方式上进行功能的增强,使异步接口更加方便统一管理、使用方式更符合日常开发习惯

何为cache

此cache说的并不是日常所说的浏览器/服务器缓存。cache也只是一个抽象概念的统称,具体映射的是对象实体的全部接口的集合。比如用户为一个实体对象,与用户这个实体相关的所有CRUD接口操作都统一放在user这个cache中,方便集中管理与维护

目前只支持异步接口的管理,如果后续集成redux等数据状态管理容器做数据的缓存与管理,命名为cache也是说得过去的。

功能

  • 接口配置与接口方法统一管理
  • 配置异步接口中后端返回http状态码与前端使用状态码映射规则,方便底层做统一处理
  • 请求接口支持restful风格API,自动替换API中参数
  • 支持非异步接口新窗口打开规则
  • 支持服务端返回状态码重置
  • 支持请求前、后介入做数据处理,抹平请求参数、返回数据格式差异
  • 支持异步接口取本地配置mock数据 (只建议临时使用)
  • 支持配置mock服务器地址,使本地可以访问任何服务器接口(跨域需服务端配合)

安装

npm install axios-cache --save

使用方法

cache使用工程结构样例

├── src
│   ├── App.js
│   ├── cache
│   │   ├── base
│   │   │   ├── cache.js
│   │   │   ├── config.js
│   │   │   └── setting.js
│   │   ├── icon
│   │   │   ├── cache.js
│   │   │   └── config.js
│   │   ├── repo
│   │   │   ├── cache.js
│   │   │   └── config.js
│   │   └── user
│   │       ├── cache.js
│   │       └── config.js

......

模块层级图

模块层级流程图

底层实现流程图 底层实现流程图

一、 工程接入做底层配置及错误统一处理

前后端返回状态码映射规则配置

// cache/base/setting.js

// 后端返回数据格式定义
// 后端操作成功
// {
//     code: 0,
//     result: true | Array | Object | ...
//     message: ""
// }

// 后端操作失败
// {
//     code: 0,
//     result: false | null
//     message: "后端返回的错误信息,由前端上层toast或弹框显示或input框报错"
// }

// 后端操作通用提示
// {
//     code: -5,
//     result: null
//     message: "后端返回的错误信息,统一toast处理"
// }

// 后端操作通用提示
// {
//     code: -10,
//     result: null
//     message: "后端返回的错误信息,统一弹框处理"
// }

export default {
    // 服务器状态码
    httpStatus: {
        CODE_OK: [200, 201, 202, 203, 204, 205, 206], // 成功
        CODE_WARM: [100, 101], // 警告
        CODE_ERROR: [500, 501, 502, 503, 504, 505], // 内部错误
        CODE_NO_AUTH: [401], // 未登录
        CODE_NO_PRIVILEGE: [403] // 无权限
    },
    // 客户端专题码
    clientCode: {
        CODE_OK: 0, // 成功 业务层处理
        CODE_WARM: -5, // 错误 全局toast提示
        CODE_ERROR: -10, // 错误 全局弹框报错
        CODE_NO_AUTH: -30, // 未登录 全局弹登陆框或跳转登陆页
        CODE_NO_PRIVILEGE: -50 // 无权限 跳转无权限页
    }
}

配置全局基本配置及请求前后对数据处理的方法

// cache/base/config.js

export default {
    // 需要开启mock时的server url
    mockBaseURL: '',
    /**
     * 请求发送之前对数据、配置进行处理
     *
     * @param    {Object}           conf                     请求配置、数据
     * @return   {void}
     */
    filter: function (conf) {

    },
    /**
     * 服务器返回的原始数据,对该数据进行整理,符合axios-cache数据格式
     *
     * @param    {Object}           result                   服务起返回原始数据
     * @param    {Object}           conf                     请求配置、数据
     * @return   {void}
     */
    post: function (result, conf) {

    },
    /**
     * 格式化返回数据,符合view层展示需求
     *
     * @param    {Object}           result                   服务起返回原始数据
     * @param    {Object}           conf                     请求配置、数据
     * @return   {void}
     */
    format: function (result, conf) {

    }
}

配置覆盖及底层统一做错误处理

// cache/base/cache.js

import AxiosCache from 'axios-cache'
import config from './config'
import setting from './setting'
import {Message, Modal} from 'iview'

const CACHE_KEY = 'axios-cache'
export default class BaseCache extends AxiosCache {
    constructor () {
        super()
        this.globalCacheKey = CACHE_KEY
    }

    init () {
        super.init()
        // 设置工程通用请求配置
        this.doFlushSetting(this.globalCacheKey, config)
        // 设置后端返回状态码与客户端状态码对应关系
        this.doMapStatusCode(setting.httpStatus, setting.clientCode)
    }

    /**
     * 处理后端返回错误状态码,子类重写
     * @override
     *
     * @param       {Integer}   code        客户端状态码
     * @param       {Object}    result      客户端返回的数据
     * @return      {void}
     */
    handleErrorCase (code, result) {
        switch (code) {
        case setting.clientCode.CODE_WARM:
            // before show this modal is removing another modal, because executing destroy
            Message.info({
                title: '错误提示!',
                content: result.message
            })
            break
        case setting.clientCode.CODE_ERROR:
        case setting.clientCode.CODE_NO_AUTH:
        case setting.clientCode.CODE_NO_PRIVILEGE:
            Modal.error({
                    title: '错误提示!',
                    content: result.message
                })
            break
        default:
            console.log('code ' + code + ', message ' + result.message)
        }
    }
}

二、上层业务具体cache实现

cache 接口配置

// user/cache.js

export default {
    'user-get': {
        url: '/api/user/:userId/get',
        method: 'get',
        rest: true
    }
}

cache 接口API

import config from './config'
import BaseCache from '../base/cache'

const CACHE_KEY = 'login_cache_key'
export default class LoginCache extends BaseCache {
    constructor () {
        super()
        this.settingKey = CACHE_KEY
    }

    init () {
        super.init()
        this.doFlushSetting(
            CACHE_KEY, config
        )
    }
    /**
     * 获取用户基本信息
     *
     * @param    {Object}           options        请求对象
     * @return   {void}
     */
    getUserInfo (options) {
        this.sendRequest(
            'user-get', options
        )
    }
}

三、具体业务调用cache

    import Base from './base.vue'
    import UserCache from '@/cache/user/cache'

    export default Base.extend({
        name: 'app',
        methods: {
            onGetUserInfo (result) {
                window.webUser = result.result
                this.$store.commit('webUser', result.result)
            }
        },
        created: function () {
            this.userCache = new UserCache({})
            this.userCache.getUserInfo({
                data: {
                	userId: 123
                },
                onload: this.onGetUserInfo.bind(this)
            })
        }
    })

当然,如果你习惯使用Promise风格的请求方式也是可以的

	....
	
    this.userCache = new UserCache({})
    this.userCache.getCurLoginUserInfo({
        data: {}
    }).then((result) => {
        this.onGetUserInfo(result)
    }).then((result) => {
        console.log(result);
    })

功能配置说明

请求接口支持restful风格API,自动替换API中参数

接口配置:

'user-get': {
    url: '/api/user/:userId/get',
    method: 'get',
    rest: true
},

接口调用传参

    this.userCache.getUserInfo({
        data: {
        	userId: 123
        },
        onload: this.onGetUserInfo.bind(this)
    })

接口最终变成 /api/user/123/get, url中参数的替换来源于接口调用时dataparams对象中的同名属性的值, 只要接口配置中加rest: true就会执行替换

支持非异步接口新窗口打开规则

接口配置:

	'icon-download': {
	    url: '/api/icon/download/:iconId',
	    method: 'get',
	    rest: true,
	    ajax: false,
	    target: '_self'
	}

接口调用时跳转到该接口

	// 源码实现
    // 非异步接口
    if (conf.ajax === false) {
        window.open(conf.url, conf.target ? conf.target : '_blank')
        return
    }

支持服务端返回状态码重置

接口配置:

	'icon-download': {
	    url: '/api/icon/download/:iconId',
	    method: 'get',
	    rest: true,
	    resetReturnCode: 200
	 }

不管后端然后状态码是什么,返回的code都会被设置为200,然后调用onload方法

支持请求前、后介入做数据处理,抹平请求参数、返回数据格式差异

接口配置:

	    'clans-list': {
        url: '/clans/v1/getPublicClans',
        method: 'get',
        mock: clans.listView,
        filter: function (conf) {
            // request add headers edu_token before send request
            Object.assign(conf.headers || {}, {
                'edu_token': '123456'
            })
        },
        // server response {result: true|false}
        post: function (result, options) {
        	// format return data to {code: xx, result: xxx, message:xxx}
            if (result.result) {
                result.code = 200
                result.message = '操作成功'
            } else {
                result.code = 500
                result.message = '操作失败'
            }
        },
        format: function (result, options) {
        	// response data ok, format it to show
            for (let item of (result.result || [])) {
                item.membersLabel = item.memberCount || (item.members || []).length
                item.typeLabel = (item.type === 'public' ? '公开' : '私有')
            }
        }
    }

对于异步请求的介入方法有三个

  • filter 请求为发送前对发送的数据、配置做处理
  • post 服务端返回的原始数据,对数据做处理成{code:xx, result:xxx, message: xx}格式
  • format 改方法属于服务端已经正确返回,在onload之前做数据格式化以符合展示需求

请求的介入会先调用全局配置的filter、post、format统一处理,单个接口需额外处理只需在该接口配置中添加这几个方法

支持异步接口取本地配置mock数据

    'clans-join': {
        url: '/clans/v1/joinClans/:clansId',
        method: 'put',
        rest: true,
        mock: {
            "code": 200,
            "message": "",
            "result": true
        }
    }

对于前端在本地开发更方便的走通流程,提供异步请求直接获取mock属性的数据,不发异步请求。当配置的mock属性存在切当前host是localhost时才会起效。但是这样做的后果是不好维护,上线需要手动删除或者在构建过程自动删除

支持配置mock服务器地址,使本地可以访问任何服务器接口(跨域需服务端配合)

对于有独立启动的服务,只需要调试异步接口时,可能需要调试测试、线上环境的数据。类似于dev-server可以独立起服务的应用, 在本地开发时需要联调测试环境的数据,只需要在全局接口配置中指定mockBaseURL的服务器地址就好。或者在单个接口中设置baseURL,并带上相应的headers

// cache/base/config.js

export default {
    mockBaseURL: 'proxy.server.com'
}

底层更多接口详细配置请参考axios

项目参考

axios-cache模块是我在开发字体图标库管理平台时所提取出来的模块,具体的使用方式可以参考该项目 nicon-front, 如有问题或建议,欢迎交流指导。

单元测试

待补充....

License

MIT