8 changed files with 272 additions and 6 deletions
-
2.env
-
17README.md
-
1package.json
-
17src/api/index.js
-
6src/components/Count.vue
-
38src/service/index.js
-
132src/service/request.js
-
57yarn.lock
@ -1 +1 @@ |
|||
VITE_APP_API_BASE_URL=http://127.0.0.1:8080/ |
|||
VITE_BASE_URL=http://127.0.0.1:8080/ |
@ -1,9 +1,26 @@ |
|||
# 技术选型 |
|||
|
|||
- 本项目采用的 vue3 + vite + js 脚手架搭建 |
|||
- 包管理工具为 Yarn |
|||
|
|||
# 代码规范 |
|||
|
|||
> 随着团队的不断扩大,每个人都有自己的 coding 风格,但是如果一个项目中的代码存在多种风格,那对于代码的可维护性和可读性都大大减少,所以说一个项目规范对于前端团队来说很重要。 |
|||
|
|||
## Prettier |
|||
|
|||
1、vscode插件 --- Prettier - Code formatter |
|||
2、.prettierrc文件 |
|||
|
|||
# 全局状态管理 |
|||
|
|||
> 使用 pinia |
|||
|
|||
# axios 封装 |
|||
|
|||
> src/service |
|||
|
|||
- 灵活的拦截器; |
|||
- 可以创建多个实例,灵活根据项目进行调整; |
|||
- 每个实例,或者说每个接口都可以灵活配置请求头、超时时间等; |
|||
- 取消请求(可以根据 url 取消单个请求也可以取消全部请求)。 |
@ -0,0 +1,17 @@ |
|||
import request from '@/service' |
|||
|
|||
export const get15DaysWeatherByArea = data => { |
|||
return request({ |
|||
url: '/api/common/weather/get15DaysWeatherByArea', |
|||
method: 'GET', |
|||
data, |
|||
interceptors: { |
|||
requestInterceptors(res) { |
|||
return res |
|||
}, |
|||
responseInterceptors(result) { |
|||
return result |
|||
}, |
|||
}, |
|||
}) |
|||
} |
@ -0,0 +1,38 @@ |
|||
import Request from './request' |
|||
/** |
|||
* 后续封装get post delete等方法的简单调用。 |
|||
*/ |
|||
|
|||
const request = new Request({ |
|||
baseURL: import.meta.env.BASE_URL, |
|||
timeout: 1000 * 60 * 5, |
|||
interceptors: { |
|||
// 请求拦截器
|
|||
requestInterceptors: config => config, |
|||
// 响应拦截器
|
|||
responseInterceptors: result => result, |
|||
}, |
|||
}) |
|||
|
|||
/** |
|||
* @description: 函数的描述 |
|||
* @param config 不管是GET还是POST请求都使用data |
|||
* @returns {Promise} |
|||
*/ |
|||
const dreamworkRequest = config => { |
|||
const { method = 'GET' } = config |
|||
if (method === 'get' || method === 'GET') { |
|||
config.params = config.data |
|||
} |
|||
return request.request(config) |
|||
} |
|||
// 取消请求
|
|||
export const cancelRequest = url => { |
|||
return request.cancelRequest(url) |
|||
} |
|||
// 取消全部请求
|
|||
export const cancelAllRequest = () => { |
|||
return request.cancelAllRequest() |
|||
} |
|||
|
|||
export default dreamworkRequest |
@ -0,0 +1,132 @@ |
|||
import axios from 'axios' |
|||
|
|||
class Request { |
|||
// axios 实例
|
|||
instance |
|||
// 拦截器对象
|
|||
interceptorsObj |
|||
|
|||
/* |
|||
存放取消方法的集合 |
|||
* 在创建请求后将取消请求方法 push 到该集合中 |
|||
* 封装一个方法,可以取消请求,传入 url: string|string[] |
|||
* 在请求之前判断同一URL是否存在,如果存在就取消请求 |
|||
*/ |
|||
cancelRequestSourceList |
|||
/* |
|||
存放所有请求URL的集合 |
|||
* 请求之前需要将url push到该集合中 |
|||
* 请求完毕后将url从集合中删除 |
|||
* 添加在发送请求之前完成,删除在响应之后删除 |
|||
*/ |
|||
requestUrlList |
|||
|
|||
constructor(config) { |
|||
this.requestUrlList = [] |
|||
this.cancelRequestSourceList = [] |
|||
this.instance = axios.create(config) |
|||
this.interceptorsObj = config.interceptors |
|||
// 拦截器执行顺序 接口请求 -> 实例请求 -> 全局请求 -> 实例响应 -> 全局响应 -> 接口响应
|
|||
this.instance.interceptors.request.use( |
|||
res => res, |
|||
err => err, |
|||
) |
|||
|
|||
// 使用实例拦截器
|
|||
this.instance.interceptors.request.use( |
|||
this.interceptorsObj?.requestInterceptors, |
|||
this.interceptorsObj?.requestInterceptorsCatch, |
|||
) |
|||
this.instance.interceptors.response.use( |
|||
this.interceptorsObj?.responseInterceptors, |
|||
this.interceptorsObj?.responseInterceptorsCatch, |
|||
) |
|||
// 全局响应拦截器保证最后执行
|
|||
this.instance.interceptors.response.use( |
|||
// 因为我们接口的数据都在res.data下,所以我们直接返回res.data
|
|||
res => { |
|||
return res.data |
|||
}, |
|||
err => err, |
|||
) |
|||
} |
|||
/** |
|||
* @description: 获取指定 url 在 cancelRequestSourceList 中的索引 |
|||
* @param {string} url |
|||
* @returns {number} 索引位置 |
|||
*/ |
|||
getSourceIndex(url) { |
|||
return this.cancelRequestSourceList?.findIndex(item => { |
|||
return Object.keys(item)[0] === url |
|||
}) |
|||
} |
|||
/** |
|||
* @description: 删除 requestUrlList 和 cancelRequestSourceList |
|||
* @param {string} url |
|||
* @returns {*} |
|||
*/ |
|||
delUrl(url) { |
|||
const urlIndex = this.requestUrlList?.findIndex(u => u === url) |
|||
const sourceIndex = this.getSourceIndex(url) |
|||
// 删除url和cancel方法
|
|||
urlIndex !== -1 && this.requestUrlList?.splice(urlIndex, 1) |
|||
sourceIndex !== -1 && this.cancelRequestSourceList?.splice(sourceIndex, 1) |
|||
} |
|||
request(config) { |
|||
return new Promise((resolve, reject) => { |
|||
// 如果我们为单个请求设置拦截器,这里使用单个请求的拦截器
|
|||
if (config.interceptors?.requestInterceptors) { |
|||
config = config.interceptors.requestInterceptors(config) |
|||
} |
|||
const url = config.url |
|||
// url存在保存取消请求方法和当前请求url
|
|||
if (url) { |
|||
this.requestUrlList?.push(url) |
|||
config.cancelToken = new axios.CancelToken(c => { |
|||
this.cancelRequestSourceList?.push({ |
|||
[url]: c, |
|||
}) |
|||
}) |
|||
} |
|||
this.instance |
|||
.request(config) |
|||
.then(res => { |
|||
// 如果我们为单个响应设置拦截器,这里使用单个响应的拦截器
|
|||
if (config.interceptors?.responseInterceptors) { |
|||
res = config.interceptors.responseInterceptors.res |
|||
} |
|||
|
|||
resolve(res) |
|||
}) |
|||
.catch(err => { |
|||
reject(err) |
|||
}) |
|||
.finally(() => { |
|||
url && this.delUrl(url) |
|||
}) |
|||
}) |
|||
} |
|||
// 取消请求
|
|||
cancelRequest(url) { |
|||
if (typeof url === 'string') { |
|||
// 取消单个请求
|
|||
const sourceIndex = this.getSourceIndex(url) |
|||
sourceIndex >= 0 && this.cancelRequestSourceList?.[sourceIndex][url]() |
|||
} else { |
|||
// 存在多个需要取消请求的地址
|
|||
url.forEach(u => { |
|||
const sourceIndex = this.getSourceIndex(u) |
|||
sourceIndex >= 0 && this.cancelRequestSourceList?.[sourceIndex][u]() |
|||
}) |
|||
} |
|||
} |
|||
// 取消全部请求
|
|||
cancelAllRequest() { |
|||
this.cancelRequestSourceList?.forEach(source => { |
|||
const key = Object.keys(source)[0] |
|||
source[key]() |
|||
}) |
|||
} |
|||
} |
|||
|
|||
export default Request |
Write
Preview
Loading…
Cancel
Save
Reference in new issue