фактическиaxiosБыло предоставлено много мощных API, и мы можем вызывать их непосредственно в реальном использовании, но каждая команда и каждый проект вызывают аксиомы по-разному, особенно в крупномасштабном командном проекте, где логика взаимодействия с бэкендом сильно отличается. конфигурация сложна, а адресов много, поэтому необходима схема запроса с единым стилем, гибкой конфигурацией и централизованным управлением.
Первый шаг, управление интерфейсом
Сначала создайте проект с именемapi
Папка используется для унифицированного управления логикой взаимодействия с фоном.
Классификация
существуетapi
Создавайте папки в папках и классифицируйте адреса интерфейса по типу (это необходимо, особенно в крупных проектах, классификация по типу позволяет быстро найти местоположение, в котором написан интерфейс):
Создать заново под каждой папкойindex.js
файл, пропишите все адреса интерфейсов, принадлежащие этому типу:
cms
...,
export const CMS_DATA = '/cms/renderData'
member
...,
export const MEMBER_INFO = '/rights/memberInfo'
бросать
существуетapi
создать папкуindex.js
документ:
Выставляйте все типы интерфейсов единообразно:
// cms信息
export * from './cms'
// 会员信息
export * from './member'
Второй шаг, механизм кэширования
существуетapi
создать папкуcache.js
документ:
на основеaxios
Разработан механизм кэширования на основе адреса запросаurl
и параметры запросаparams
Кэшируйте каждый результат запроса, и вы можете установить лимит кеша и режим кеша для каждого результата запроса:
export default class Cache {
constructor(axios, config = {}) {
this.axios = axios
this.caches = []
if (!this.axios) {
throw new Error('请传入axios实例')
}
this.config = config
this.defaultConfig = {
cache: false,
expire: 100 * 1000
}
this.CancelToken = this.axios.CancelToken
this.init()
}
init() {
this.requestInterceptor(this.config.requestInterceptorFn)
this.responseInterceptor(this.config.responseInterceptorFn)
window.onbeforeunload = () => {
this.mapStorage()
}
}
requestInterceptor(callback) {
this.axios.interceptors.request.use(async config => {
let newConfig = callback && (await callback(config))
config = newConfig || config
let { url, data, params, cacheMode, cache = this.defaultConfig.cache, expire = this.defaultConfig.expire } = config
if (cache === true) {
let getKey = data ? `${url}?cacheParams=${data}` : `${url}?cacheParams=${params}`
let obj = this.getStorage(cacheMode, getKey)
// 判断缓存数据是否存在
if (obj) {
let curTime = this.getExpireTime()
let source = this.CancelToken.source()
config.cancelToken = source.token
// 判断缓存数据是否存在,存在的话是否过期,如果没过期就停止请求返回缓存
if (curTime - obj.expire < expire) {
source.cancel(obj)
} else {
this.removeStorage(cacheMode, url)
}
}
} else {
this.clearStorage(url)
}
return config
}, error => {
return Promise.reject(error)
})
}
responseInterceptor(callback) {
this.axios.interceptors.response.use(async response => {
let newResponse = callback && (await callback(response))
response = newResponse || response
// the http request error, do not store the result, direct return result
if (response.status !== 200 || response.data.ret || !response.data.success) {
return response.data
}
/*
* `data` is the data to be sent as the request body, only applicable for request methods 'PUT', 'POST', and 'PATCH'
* `params` are the URL parameters to be sent with the request, can be applicable for request methods 'GET'
*/
let { url, cache, cacheMode, data, params } = response.config
if (cache === true) {
let obj = {
expire: this.getExpireTime(),
params,
data,
result: response.data
}
let setKey = data ? `${url}?cacheParams=${data}` : `${url}?cacheParams=${params}`
this.caches.push(setKey)
this.setStorage(cacheMode, setKey, obj)
}
return response.data
}, error => {
let newError = callback && (await callback(newError))
error = newError || error
// 返回缓存数据
if (this.axios.isCancel(error)) {
return Promise.resolve(error.message.result)
}
return Promise.reject(error)
})
}
// 设置缓存
setStorage(mode = 'sessionStorage', key, cache) {
window[mode].setItem(key, JSON.stringify(cache))
}
// 获取缓存
getStorage(mode = 'sessionStorage', key) {
let data = window[mode].getItem(key)
return JSON.parse(data)
}
// 清除缓存
removeStorage(mode = 'sessionStorage', key) {
window[mode].removeItem(key)
}
// 设置过期时间
getExpireTime() {
return new Date().getTime()
}
// 清空缓存
clearStorage(key) {
if (window.localStorage.getItem(key)) {
window.localStorage.removeItem(key)
} else {
window.sessionStorage.removeItem(key)
}
}
// 清空没用到的缓存
mapStorage() {
let length = window.localStorage.length
if (length) {
for (let i = 0; i < length; i++) {
let key = window.localStorage.key(i)
if (!this.caches.includes(key) && key.includes('?cacheParams=')) {
window.localStorage.removeItem(key)
}
}
}
}
}
Поскольку механизм кэширования основан на
url+params
Чтобы кэшировать, снова получите доступ к тому же в течение периода действияurl+params
, браузер будет напрямую читать кеш и больше не будет отправлять запрос. В случае истечения срока действия или изменения адреса запроса или изменения параметров запроса браузер минует кеш и отправит запрос напрямую. (Сценарии, поддерживающие кэш подкачки)
Шаг 3: Настройте Axios
существуетapi
создать папкуconfig.js
файл для храненияaxios
Некоторая информация перед конфигурацией:
Глобальная конфигурация
import axios from 'axios'
import Cache from './cache'
axios.defaults.withCredentials = true
axios.defaults.baseURL = process.env.NODE_ENV === 'production' ? '' : '/api'
axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded; charset=UTF-8'
axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest'
...
перехватчик
Поскольку разработанный механизм кэширования основан на механизме перехватчика, чтобы избежать дополнительной настройки перехватчика, запись конфигурации перехватчика зарезервирована при разработке механизма кэширования следующим образом:
new Cache(axios, {
requestInterceptorFn: config => {
// 自定义请求拦截器
/* */
// 需要用Promise将config返回
return Promise.resolve(config)
},
responseInterceptorFn: response => {
// 自定义响应拦截器,可统一返回的数据格式也可拦截错误
/* */
// 需要用Promise将response返回
return Promise.resolve(response)
}
})
export default axios
Если механизм кэширования не используется, перехватчик можно настроить напрямую следующим образом:
axios.interceptors.request.use(config => {
// Do something before request is sent
return config;
}, error => {
// Do something with request error
return Promise.reject(error);
});
// Add a response interceptor
axios.interceptors.response.use(response => {
// Do something with response data
return response || {};
}, error => {
// Do something with response error
return Promise.reject(null);
});
export default axios
Четвертый шаг, запрос упаковки
существуетapi
создать папкуbase.js
документ:
В основном инкапсулирует несколько часто используемых методов, вот наиболее часто используемые методыget
а такжеpost
метод:
import axios from './config'
import qs from 'qs'
export const post = (url, data, extend = {isJson: true, cache: false}) => {
let defaultConfig = {
url,
method: 'POST',
data: extend.isJson ? data : qs.stringify(data) // 通过isJson来确定传参格式是json还是formData,默认是json
}
let config = {...defaultConfig, ...extend}
return axios(config).then(res => {
// 可以统一返回的数据格式
return res
}, err => {
return Promise.reject(err)
})
}
export const get = (url, data, extend = {cache: false}) => {
let defaultConfig = {
url,
method: 'GET',
params: data
}
let config = {...defaultConfig, ...extend}
return axios(config).then(res => {
// 可以统一返回的数据格式
return res
}, err => {
return Promise.reject(err)
})
}
Пятый шаг, глобальная регистрация
существуетapi
создать папкуinstall.js
документ:
Зарегистрируйте инкапсулированный метод глобально:
import { get, post } from 'api/base'
export const install = function(Vue, config = {}) {
Vue.prototype.$_get = get
Vue.prototype.$_post = post
}
существуетmain.js
написать в:
import { install as Axios } from './api/install'
Vue.use(Axios)
Шестой шаг, звонок
При вызове вам нужно только ввести адрес интерфейса, который вы хотите вызвать:
import { CMS_DATA, MEMBER_INFO } from 'api'
methods: {
receiveCMS() {
// post参数形式为formData
this.$_post(CMS_DATA, data, { jsJson: false }).then(res => {
console.log(res)
}),
},
receiveMember() {
// 开启缓存,设置缓存时间为一个小时,缓存的模式为localStorage
this.$_get(MEMBER_INFO, data, { cache: true, expires: 1000 * 60 * 60, cacheMode: 'localStorage' }).then(res => {
console.log(res)
}),
}
}
Кэш по умолчанию отключен, и его необходимо включить вручную.Если этот параметр включен, срок действия кеша по умолчанию составляет 10 минут, а режим кеша по умолчанию
sessionStorage
.
наконец
Вся разработанная схема завершена:
Конечно, со сложностью проекта, в этом решении еще много областей, которые можно оптимизировать, например, глобальная загрузка, потому что лично я считаю, что оно подходит для мобильных терминалов и не подходит для ПК-терминалов, поэтому я не буду приведите примеры здесь шаг для инкапсуляции. Например, глобальную конфигурацию можно дополнить на третьем шаге.
Этот план не самый лучший, но это самый элегантный способ, который я подытожил на данный момент.Я также приветствую ваши ценные мнения.