[toc]

前言

功能点

此文主要是基于vuecli3项目中axios封装及api管理的实践记录及过程中的踩坑收获,功能基本都是根据工作中需求实现。需求背景是,在同一套请求配置下,实现以下主要功能:

• 自定义请求配置• 设置全局拦截器• 响应成功及异常的全局拦截统一处理• 防止重复请求(取消当前重复的请求)• 路由切换取消当前所有pending状态的请求(可配置白名单)• 单独取消发出的某个请求• api统一管理

axios一些特性

在开始之前,首先明确一些axios的特性,这些特性会影响到某些功能的实现方式:

1.通过axios.create()方法创建的实例对象只有常见的数据请求方法,没有取消请求、并发请求等方法。可通过Object.keys()将所有的key打印出来对比得知。2.axios拦截器是可以累加的,每添加一个拦截器,就会返回一个对应的拦截器id,也就是无法通过新增拦截的方式覆盖或者改变已有拦截器的配置。但可以利用拦截器id通过axios.interceptors.request.eject(InterceptorId)方法移除指定拦截器。3.对于同一个axios对象,如果全局拦截器中设置了CancelToken属性,就无法在单独的请求中再通过此属性取消请求。移除全局拦截器可以解决这个问题,但又会有另一个问题,拦截器移除后就永远失效了,影响是全局的。4.axios中以别名的形式(axios.get、axios.post)发请求,不同的请求方式参数的写法是不一样的,主要是put/post/patch三种方法与其他不太一样

自定义请求配置

根目录下新建plugins/axios/index.js文件,自定义axios的请求配置。

这里process.env.VUE_APP_BASEURL是一个定义好的变量,值为"/webapi";

设置超时时间timeout为10s。如下:

import axios from 'axios'axios.defaults.baseURL = process.env.VUE_APP_BASEURLaxios.defaults.timeout = 10000axios.defaults.headers['custom-defined-header-key'] = 'custom-defined-header-value'// 自定义请求头:对所有请求方法生效axios.defaults.headers.common['common-defined-key-b'] = 'custom value: for all methods'// 自定义请求头:只对post方法生效axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';// 自定义请求头:只对get方法生效axios.defaults.headers.get['get-custom-key'] = 'custom value: only for get method';export default axios

"main.js"文件:

import request from '@/plugins/axios/index.js'Vue.prototype.$request = request

这样在组件内就可以通过this.$request(options)或者this.$request.get(options)的方法来请求数据了。

对常见的响应情况统一处理

这里主要是在"响应拦截器"中,对于一些常见的请求状态码和跟后端约定好的请求返回码做统一的前置处理。

新建axios.handleResponse.js文件,用于处理常见的正常响应:

# axios.handleResponse.js// 处理响应错误码export default (response) => {    const status = response.status    // 如果http响应状态码response.status正常,则直接返回数据    if ((status >= 200 && status <= 300) || status === 304) {        return response    }    // status不正常的话,根据与后端约定好的code,做出对应的提示与处理    // 返回一个带有code和message属性的对象    else {        const code = parseInt(response.data && response.data.code)        // msg为服务端返回的错误信息,字段名自定义,此处以msg为例        let message = (response.data || {}).msg        switch (code) {            case 400:                break            case 4001:                if (process.server) return                message = message || '登录设备数量超出限制'                // store.commit('savehttpResult', { res: response.data })                break            case 403:                message = message || '未登录'                break            case 404:                message = message || '请求地址错误'                break            case 412:                message = message || '未找到有效session'                break            default:                // message = message || err.response.data.msg                break        }        return {            code,            message        }    }}

新建plugins/axios/axios.handleError.js文件,用于处理常见的异常响应:

#plugins/axios/axios.handleError.js文件export default (err) => {    const { response } = err    if (!response.status) {        err.code = ''        err.message = '有response但没有response.status的情况'    }    err.code = response.status    switch (response.status) {        case 200:            err.message = '错误响应也会有状态码为200的情况'            break        case 400:            err.message = '请求错误(400)'            break        case 401:            err.message = '未授权,请重新登录(401)'            break        case 403:            err.message = '拒绝访问(403)'            break        case 404:            err.message = '请求出错(404)'            break        case 408:            err.message = '请求超时(408)'            break        case 500:            err.message = '服务器错误(500)'            break        case 501:            err.message = '服务未实现(501)'            break        case 502:            err.message = '网络错误(502)'            break        case 503:            err.message = '服务不可用(503)'            break        case 504:            err.message = '网络超时(504)'            break        case 505:            err.message = 'HTTP版本不受支持(505)'            break        default:            err.message = `连接出错,状态码:(${err.response.status})!`    }    return err}

plugins/axios/index.js文件中引入并在拦截器中配置:

•如果请求被取消,会进入到响应拦截器的第二个参数err处理中

#plugins/axios/index.js文件import axios from 'axios'import handleResponse from '@/plugins/axios/axios.handleResponse.js'import handleError from '@/plugins/axios/axios.handleError.js'import { Message } from 'element-ui'const showTip = (tip)=>{    Message({        type: 'warning',        message: tip || '请求出错啦',        duration: 1500    })}/** * 请求拦截 */axios.interceptors.request.use(    (config) => {        // 在发送请求之前做些什么,例如把用户的登录信息放在请求头上        // config.headers.common['cookie-id'] = cookieId        return config    },    (err) => {        // 对请求错误做些什么        Promise.reject(err)    })/** * 响应拦截 */axios.interceptors.response.use(    (response) => {        showTip(err.message)        return Promise.resolve(handleResponse(response)),    }    // 对异常响应处理    (err) => {        if (!err) return Promise.reject(err)        if (err.response) {            err = handleError(err)        }        // 没有response(没有状态码)的情况        // eg: 超时;断网;请求重复被取消;主动取消请求;        else {            // 错误信息err传入isCancel方法,可以判断请求是否被取消            if (axios.isCancel(err)) {                throw new axios.Cancel(err.message || `请求'${request.config.url}'被取消`)            } else if (err.stack && err.stack.includes('timeout')) {                err.message = '请求超时!'            } else {                err.message = '连接服务器失败!'            }        }        showTip(err.message)        return Promise.reject(err)    })

到这里对于一些常见的响应,例如断网、未登录、登录信息失效、超时等,我们可以请求拦截器中通过showTip做出统一的ui提示,就不用每次请求之后再重复得处理这些逻辑了。

接下来就是在"请求拦截器"中配置实现防止重复请求的功能。

防止重复请求

axios提供了两种取消请求的方法:

我们的防止重复请求思路:

在请求拦截器中,通过第二个种方法给每个请求定义cancelToken属性,同时声明一个变量pendingPool,用于并保存pending状态的请求及对应的cancelFn

在响应拦截器中,无论请求成功了还是失败了,都通过api地址将这个请求从pendignPool中删除。

然后每次发起请求前做一个判断,如果pendingPool中没有这个请求,正常发出;如果已存在说明当前请求还是pending状态,那么执行cancelFn取消当前重复的请求。

pendingPool声明为Map类型的数据结构,可以方便得通过set/has/delete等进行判断、删除等操作。key值为api地址,value值为一个对象,保存cancelFnglobal(global用于后面的路由切换取消所有请求,可以暂时忽略)。pendingPool的大概结构:

Map { '/home/banner' => { cancelFn: [Function: c], global: false }, '/login' => { cancelFn: [Function: c], global: false } }

请求拦截器中可以拿到每个请求的配置信息config,添加cancelToken属性:

#plugins/axios/index.js文件import axios from 'axios'// 请求中的apilet pendingPool = new Map()/** * 请求拦截 */axios.interceptors.request.use(    (config) => {        // 对于异常的响应也需要在pendingPool中将其删除,但响应拦截器中的异常响应有些获取不到请求信息,这里将其保存在实例上        request.config = Object.assign({}, config)        // 在发送请求之前做些什么,例如把用户的登录信息放在请求头上        // config.headers.common['cookie-id'] = cookieId        config.cancelToken = new axios.CancelToken((cancelFn) => {            pendingPool.has(config.url) ? cancelFn(`${config.url}请求重复`) : pendingPool.set(config.url, { cancelFn, global: config.global })        })        return config    },    (err) => {        console.log('请求拦截err:', err)        // 对请求错误做些什么        Promise.reject(err)    })

响应拦截器中对有结果(正常及异常)的请求进行删除:

#plugins/axios/index.js文件axios.interceptors.response.use(    // 处理正常响应    (response) => {        // 删除        const { config } = response        pendingPool.delete(config.url)        showTip(err.message)        return Promise.resolve(handleResponse(response))    },    // 处理异常响应    (err) => {        const { config } = request        // 异常响应删除需要加一个判断:是否为请求被取消的异常,如果不是才会将这个请求从pendingPool中删除。        // 否则会出现一种情况:网速非常慢的情况下,在网速非常慢的情况下多次重复发送同一个请求,第一个请求还在pending状态中,        // 第二个请求发不出去会直接被cancel掉进入到异常响应,然后从pendignPool中删除,第三次请求发出的时候就无法正确判断这个请求是否还是pending状态会正常发出        if (!axios.isCancel(err)) pendingPool.delete(config.url)        if (!err) return Promise.reject(err)        if (err.response) {            err = handleError(err)        }        // 没有response(没有状态码)的情况        // eg: 超时;断网;请求重复被取消;主动取消请求;        else {            // 错误信息err传入isCancel方法,可以判断请求是否被取消            if (axios.isCancel(err)) {                throw new axios.Cancel(err.message || `请求'${request.config.url}'被取消`)            } else if (err.stack && err.stack.includes('timeout')) {                err.message = '请求超时!'            } else {                err.message = '连接服务器失败!'            }        }        // showTip(err.message)        return Promise.reject(err)    })

到这里就实现了防止重复请求的功能。如果同时发出多个相同的请求,前面请求还在pending状态的情况下,后面发出的请求都会被自动取消并reject到请求的catch处理中。

单独取消指定请求

但实际应用中还有一种情况:需要手动取消指定的某个请求,例如终止文件上传。根据文章开头提到的特性[3]得知,此时我们是无法单独取消某个特定请求的。

又由于特性[1]我们知道,想要单独取消指定请求,这个axios对象需要满足两个条件:1.请求拦截器中不能配置cancelToken 2. 这个axiso对象不能通过axios.create()方法实例化生成。

所以解决思路的大概要点是:

需要两个axios对象分别处理请求防重和单独取消特定请求

两个axiso对象的请求配置像baseURL等请求头信息需要是一样的

直接用axios对象(除了请求头信息,不做任何其他配置)发需要单独取消的请求,这里声明为intactRequest

通过axios.create()方法实例化生成一个新axios对象,做最完善的配置(防止重复请求、清除所有pending状态请求等、响应拦截等),作为主要发请求的对象,这里声明为request

根目录下新建plugins/axios/axios.setConfig.js文件,导出一个自定义axios默认配置的方法:

#"axios.setConfig.js"文件/** * @param {axios} axios实例 * @param {config} 自定义配置对象,可覆盖掉默认的自定义配置 */export default (axios, config = {}) => {    const defaultConfig = {        baseURL: process.env.VUE_APP_BASEURL,        timeout: 10000,        headers: {            'Content-Type': 'application/json;charset=UTF-8',            'custom-defined-header-key': 'custom-defined-header-value',            // 自定义请求头:对所有请求方法生效            common: {                'common-defined-key-b': 'custom value: for all methods'            },            // 自定义请求头:只对post方法生效            post: {                'post-custom-key': 'custom value: only for post method'            },            // 自定义请求头:只对get方法生效            get: {                'get-custom-key': 'custom value: only for get method'            }        }    }    Object.assign(axios.defaults, defaultConfig, config)    return axios}

修改plugins/axiso/index.js文件,通过setConfig方法生成两个具有相同请求头信息的axios对象,并且对request对象做请求防重、响应封装处理:

import axios from 'axios'import setConfig from '@/plugins/axios/axios.setConfig.js'/** * intactRequest是只在axios基础上更改了请求配置。 * 而request是基于axios创建的实例,实例只有常见的数据请求方法,没有axios.isCancel/ axios.CancelToken等方法, * 也就是没有**取消请求**和**批量请求**的方法。 * 所以如果需要在实例中调用取消某个请求的方法(例如取消上传),请用intactRequest。 */let intactRequest = setConfig(axios)let request = setConfig(intactRequest.create())// 请求中的apilet pendingPool = new Map()/** * 请求拦截 */request.interceptors.request.use(    //...)/** * 响应拦截 */request.interceptors.response.use(    // ...)export { intactRequest, request }

修改main.js文件,把两个对象都挂载到Vue示实例上:

import Vue from 'vue'import * as requests from '@/plugins/axios/index'Vue.prototype.$request = requests.requestVue.prototype.$intactRequest = requests.intactRequest

这样就实现了通过this.$requese发出的重复请求可以自动被取消掉,并且统一处理一些常见的响应;通过this.$intactRequest发出的请求可以通过在请求中给config.cancelToken设置”cancel token“来手动取消。

一键清除所有pending状态请求

在路由切换时可以取消当前仍在pending状态的请求从而优化性能、节约资源。

上面的pendingPool已经保存了所有pending状态的请求,封装一个方法,拿到其中每个请求然后执行cancelFn,然后每次路由切换的时候执行这个方法即可。但不排除有些api请求是全局的不能被取消。所以这个方法基础上新增白名单和请求的global参数。

plugins/axios/index.js中新增clearPendingPool方法,

/** * 清除所有pending状态的请求 * @param {Array} whiteList 白名单,里面的请求不会被取消 * 返回值 被取消了的api请求 */function clearPendingPool(whiteList = []) {    if (!pendingPool.size) return    // const pendingUrlList = [...pendingPool.keys()].filter((url) => !whiteList.includes(url))    const pendingUrlList = Array.from(pendingPool.keys()).filter((url) => !whiteList.includes(url))    if (!pendingUrlList.length) return    pendingUrlList.forEach((pendingUrl) => {        // 清除掉所有非全局的pending状态下的请求        if (!pendingPool.get(pendingUrl).global) {            pendingPool.get(pendingUrl).cancelFn()            pendingPool.delete(pendingUrl)        }    })    return pendingUrlList}request.clearPendingPool = clearPendingPool

在路由的配置文件src/router/idnex.js中,引入request,并在路由全局前置守卫中执行clearPendingPool方法:

import { request } from '@/plugins/axios/index'// 路由全局前置守卫router.beforeEach((to, from, next) => {    // 路由变化时取消当前所有非全局的pending状态的请求    request.clearPendingPool()    next()})

到这里就实现了路由切换取消pending状态的请求。可以通过两种方式指定某些api不被取消:

1.执行clearPendingPool时传入一个白名单列表:

const globalApi = [    '/global/banner',    '/global/activity']request.clearPendingPool(globalApi)

1.发起请求的时候携带global参数,默认为false:

this.$request.get('/global/banner',{    params:{page: 1},    global: true})this.$request.post('/user/login',{    name: 'xxx',    pwd:'123456'},{    global:  true})

移除拦截器

根据特性[2]知道拦截器是可以累加也可以移除的。封装两个移除的全局拦截的方法并挂载到request对象上。目前看来还没有实际应用场景,只是做一下记录。

plugins/axios/index.js文件中新增两个方法:

/** * 请求拦截 */const requestInterceptorId = request.interceptors.request.use(    // ...    )/** * 响应拦截 */const responseInterceptorId = request.interceptors.response.use(    // ...    )// 移除全局的请求拦截器function removeRequestInterceptors() {    request.interceptors.request.eject(requestInterceptorId)}// 移除全局的响应拦截器function removeResponseInterceptors() {    request.interceptors.response.eject(responseInterceptorId)}request.removeRequestInterceptors = removeRequestInterceptorsrequest.removeResponseInterceptors = removeResponseInterceptors

通过this.$request.removeRequestInterceptorsthis.$request.removeResponseInterceptors调用即可。

api管理

这里我们把所有的api地址及对应的请求方式放在一起管理,然后组件中通过别名直接调用即可。

先具体了解一下特性[3]提到aixos不同的请求方式参数的写法问题:主要由于postputpatch三种方法相比其他方法多一个data属性,也就是需要在请求体中携带的数据,其他方法会自动忽略data属性;而params属性是所有方法都有的,与请求一起发送的 URL 参数。

axios发起请求大概有两种写法:

1.直接通过axios:axios(config)的形式2.通过axios别名的形式:axiso[method]()

通过别名的形式发起请求,postputpatch三种方法需要接收三个参数:axios[method](api, data, headersConfig),第二个参数data就是需要在请求体中携带的参数;而且他方法只接收两个参数,不需要第二个参数data

根目录下新建一个src/api/index.js文件:

/**api管理页面 * apiMap: 统一管理所有api地址、对应的请求方式及自定义别名 * 导出一个对象requestMap,属性名为apiMap中定义的别名,也就是调用时的名称,值为实际请求方法 * 方法接收两个对象参数,第一个为需要传递的数据,第二个为请求头的配置信息。 * 语法: api[alias](paramsOrData, headersConfig) * 第一个参数:如果为put/post/patch方法中的一种,会被转化为data属性;其余则是params * 第二个参数:请求头信息 * * let xx = await this.$api.getBanner({ account: '18038018084', psw: '2' }) * let vv = await this.$api.login({ account: '18038018084', psw: '2' }) * * 如果类似post的方法需要通过url后缀形式传递参数,在第二个参数config加上params属性即可: * let vv = await this.$api.login({ account: '18038018084', psw: '2' },{ params: {} }) * * 自定义请求头信息: * let xx = await this.$api.getBanner({}, {timeout: 1000, headers:{ aaa: 111 }}) */import { request } from '@/plugins/axios/index'// import qs from 'qs'// console.log('qs:', qs)const apiMap = {    getBanner: { method: 'get', url: '/home/banner' },    login: { method: 'post', url: '/login' }}function injectRequest(apiObj) {    const requestMap = {}    Object.keys(apiObj).forEach((alias) => {        let { method, url, config } = apiObj[alias]        method = method.toUpperCase()        requestMap[alias] = (dataOrParams = {}, instanceConf = {}) => {            const keyName = ['PUT', 'POST', 'PATCH'].includes(method) ? 'data' : 'params'            return request({                method,                url,                // [keyName]: method === 'POST' ? qs.stringify(dataOrParams) : dataOrParams,                [keyName]: dataOrParams,                ...Object.assign(config || {}, instanceConf)            })        }    })    return requestMap}export default injectRequest(apiMap)

mains.js中引入并挂载到vue实例:

import Vue from 'vue'import api from '@/api/index.js'Vue.prototype.$api = api

调用示例:

// 请求头信息const headersConfig = {    timeout: 5000,    global: true,    headers:{        aaa: 'vvv'    }}// get请求this.$api.getBanner({    page: 1,})// get请求,自定义请求头信息this.$api.getBanner({    page: 1,}, headersConfig)// post请求this.$api.login({    account: 'laowang',    pwd: 'xxxx'})// post请求,自定义请求头信息this.$api.login({    account: 'laowang',    pwd: 'xxxx'}, headersConfig)

总结

最终项目中相关文件的目录结构:

├── CHANGELOG.md├── README.md├── package.json├── src│   ├── api│   │   └── index.js  // api管理│   ├── plugins│   │   ├── axios  // axios封装│   │   │   ├── axios.handleError.js│   │   │   ├── axios.handleResponse.js│   │   │   ├── axios.setConfig.js│   │   │   └── index.js│   ├── router│   │   ├── index.js└── yarn.lock

src/plugins/axios/index.js文件最终:

import axios from 'axios'import setConfig from '@/plugins/axios/axios.setConfig.js'import handleResponse from '@/plugins/axios/axios.handleResponse.js'import handleError from '@/plugins/axios/axios.handleError.js'// import store from '@/store/index'// import router from '@/router/index.js'import { Message } from 'element-ui'const showTip = (tip)=>{    Message({        type: 'warning',        message: tip || '请求出错啦',        duration: 1500    })}/** * intactRequest是只在axios基础上更改了请求配置。 * 而request是基于axios创建的实例,实例只有常见的数据请求方法,没有axios.isCancel/ axios.CancelToken等方法, * 也就是没有**取消请求**和**批量请求**的方法。 * 所以如果需要在实例中调用取消某个请求的方法(例如取消上传),请用intactRequest。 */let intactRequest = setConfig(axios)let request = setConfig(intactRequest.create())// 请求中的apilet pendingPool = new Map()/** * 请求拦截 */const requestInterceptorId = request.interceptors.request.use(    (config) => {        // 对于异常的响应也需要在pendingPool中将其删除,但响应拦截器中的异常响应有些获取不到请求信息,这里将其保存在实例上        request.config = Object.assign({}, config)        // 在发送请求之前做些什么        // config.headers.common['cookie-id'] = cookieId        config.cancelToken = new axios.CancelToken((cancelFn) => {            pendingPool.has(config.url) ? cancelFn(`${config.url}请求重复`) : pendingPool.set(config.url, { cancelFn, global: config.global })        })        return config    },    (err) => {        console.log('请求拦截err:', err)        // 对请求错误做些什么        return Promise.reject(err)    })/** * 响应拦截 */const responseInterceptorId = request.interceptors.response.use(    (response) => {        const { config } = response        pendingPool.delete(config.url)        // console.log('响应response suc:', response)        showTip(err.message)        return Promise.resolve(handleResponse(response))    },    // 对异常响应处理    (err) => {        const { config } = request        if (!axios.isCancel(err)) pendingPool.delete(config.url)        if (!err) return Promise.reject(err)        if (err.response) {            err = handleError(err)        }        // 没有response(没有状态码)的情况        // eg: 超时;断网;请求重复被取消;主动取消请求;        else {            // 错误信息err传入isCancel方法,可以判断请求是否被取消            if (axios.isCancel(err)) {                throw new axios.Cancel(err.message || `请求'${request.config.url}'被取消`)            } else if (err.stack && err.stack.includes('timeout')) {                err.message = '请求超时!'            } else {                err.message = '连接服务器失败!'            }        }        showTip(err.message)        return Promise.reject(err)    })// 移除全局的请求拦截器function removeRequestInterceptor() {    request.interceptors.request.eject(requestInterceptorId)}// 移除全局的响应拦截器function removeResponseInterceptor() {    request.interceptors.response.eject(responseInterceptorId)}/** * 清除所有pending状态的请求 * @param {Array} whiteList 白名单,里面的请求不会被取消 * 返回值 被取消了的api请求 */function clearPendingPool(whiteList = []) {    if (!pendingPool.size) return    // const pendingUrlList = [...pendingPool.keys()].filter((url) => !whiteList.includes(url))    const pendingUrlList = Array.from(pendingPool.keys()).filter((url) => !whiteList.includes(url))    if (!pendingUrlList.length) return    pendingUrlList.forEach((pendingUrl) => {        // 清除掉所有非全局的pending状态下的请求        if (!pendingPool.get(pendingUrl).global) {            pendingPool.get(pendingUrl).cancelFn()            pendingPool.delete(pendingUrl)        }    })    return pendingUrlList}request.removeRequestInterceptor = removeRequestInterceptorrequest.removeResponseInterceptor = removeResponseInterceptorrequest.clearPendingPool = clearPendingPoolexport { intactRequest, request }

限时秒杀阿里云服务器ECS、云数据库MySQL、对象存储OSS等多种代金券[1]

References

[1] 限时秒杀阿里云服务器ECS、云数据库MySQL、对象存储OSS等多种代金券: https://promotion.aliyun.com/ntms/yunparter/invite.html?userCode=r3wvl61d

axios post object object_一套全面又有实际意义的axios封装+api管理方案相关推荐

  1. axios post object object_深入学习Axios源码(构建配置)

    axios是我们日常代码中常用的一个http库,它可以用来在浏览器或者node.js中发起http请求:它强大的功能和简单易用的API受到了广大前端童鞋们的青睐:那么它内部是如何来实现的呢,让我们走进 ...

  2. python封装api给vue_Vue axios api统一管理的封装

    axios的封装 首先在项目的src目录中,新建一个request文件夹,而后在里面新建一个http.js.http.js文件用来封装咱们的axios.vue http.js中axios封装的优化,先 ...

  3. 推荐免费下载430套大型商业源码 ERP源码 企业信息化管理咨询

    推荐免费下载430套大型商业源码 ERP源码 企业信息化管理咨询 下载地址:http://www.hur.cn/tg/linkin.asp?linkid=165337 PB-商业源码   金科信进销存 ...

  4. axios封装,api接口封装统一管理

    axios封装,api接口封装统一管理 一. axios说明 Axios 是一个基于 promise 的 HTTP 库,可以用在浏览器和 node.js 中. axios的封装和api接口的统一管理, ...

  5. axios post object object_Vue前端开发——数据交互axios

    Axios 是一个基于 promise 的 HTTP 库,可以用在浏览器和 node.js 中 说明: 本文介绍Vue 开发中对axios 的封装处理,不对axios 概念详细介绍 项目api基本结构 ...

  6. muduo网络库学习(二)对套接字和监听事件的封装Channel

    muduo对描述符fd,需要监听的事件events,当fd被激活调用的可读/可写/关闭/错误回调函数进行了封装,实现在Channel类中,Poller监听的其实就是一个个Channel对象,Chann ...

  7. Vue3 --- axios 简单封装APi

    1. get请求 let base = ' ' ; const getRequest = (url,params) =>{ return axios({ url:  `${base}${url} ...

  8. axios跨域携带cookie_vue 本地调试跨域---带cookies(axios)

    cookise跨域第二期之便捷优雅的本地调试(axios) 1.打开config/index.js,在proxyTable中添写如下代码: proxyTable: { '/agent': { //使用 ...

  9. axios请求拦截器错误_React中使用高阶组件和axios的拦截器,统一处理请求失败提示...

    在前端开发中,判断边界条件和重要,通常我们要花费开发中的很大一部分时间做边界条件处理.发送ajax请求时,假设有这样一个需求: 每个页面发送ajax请求,如果请求失败,在页面上统一弹出样式一样的错误提 ...

最新文章

  1. NSAssert和NSLog
  2. 【调试工具】tcpdump
  3. ExtendTableView
  4. 腾讯AI单挑碾压王者荣耀职业玩家:人类15场只能赢1局,坚持不到8分钟 | “绝悟”技术细节披露...
  5. ip地址管理与子网的划分二
  6. 实现 OutOfMemory​
  7. numpy genfromtxt 读取字符_numpy组队学习1: 输入输出
  8. 浙江高级会计师评审计算机要求,浙江2020年高级会计师评审申报论文要求
  9. 用python爬取知识星球
  10. Zxing 竖屏切换 android
  11. 批处理启动myeclipse
  12. 如何使用git命令将本地项目上传到Gitlab上
  13. JavaWeb 基础系列篇
  14. 史上最全科研网站!!!
  15. 《Redis开发与运维》读书笔记三
  16. Win10 微软拼音添加小鹤双拼
  17. 基于javaweb+JSP+Servlet宿舍管理系统(超级管理员、宿舍管理员、学生)
  18. 如何进行IT服务管理系统/IT运维管理系统/ITSM选型?
  19. 打印机显示扫描到当前计算机不可用,打印时显示当前打印机不可用
  20. C语言链表怎么合并同类项,求一个关于合并同类项的编程

热门文章

  1. windows下实现校园网自动登陆
  2. Ext3.x版本锁定列和多表头的插件,BUG修复版
  3. matlab顺序消元法例题,求助,关于用matlab解列主元消去法的题
  4. 求弹性模量和泊松比计算题_弹性模量E和泊松比.doc
  5. cmac神经网络 matlab,基于CMAC 神经网络的PID 控制.pdf
  6. android framelayout view上下层_理解并测试什么是Android事件分发
  7. 黑盒、白盒、灰盒验证
  8. 马匹赛跑java_java马匹赛跑.docx
  9. php mhash,PHP加密扩展库-Mhash扩展库实例用法详解
  10. Java高频面试题解析,直戳面试官痛点,多家互联网大厂Offer等你拿