Browse Source

feature: 封装axios

master
maochaoying 2 years ago
parent
commit
fb3604e4bd
  1. 2
      .env
  2. 25
      README.md
  3. 1
      package.json
  4. 17
      src/api/index.js
  5. 6
      src/components/Count.vue
  6. 38
      src/service/index.js
  7. 132
      src/service/request.js
  8. 57
      yarn.lock

2
.env

@ -1 +1 @@
VITE_APP_API_BASE_URL=http://127.0.0.1:8080/
VITE_BASE_URL=http://127.0.0.1:8080/

25
README.md

@ -1,9 +1,26 @@
# 技术选型 # 技术选型
- 本项目采用的vue3 + vite + js脚手架搭建
- 包管理工具为Yarn
- 本项目采用的 vue3 + vite + js 脚手架搭建
- 包管理工具为 Yarn
# 代码规范 # 代码规范
> 随着团队的不断扩大,每个人都有自己的coding风格,但是如果一个项目中的代码存在多种风格,那对于代码的可维护性和可读性都大大减少,所以说一个项目规范对于前端团队来说很重要。
## Prettier
> 随着团队的不断扩大,每个人都有自己的 coding 风格,但是如果一个项目中的代码存在多种风格,那对于代码的可维护性和可读性都大大减少,所以说一个项目规范对于前端团队来说很重要。
## Prettier
1、vscode插件 --- Prettier - Code formatter 1、vscode插件 --- Prettier - Code formatter
2、.prettierrc文件 2、.prettierrc文件
# 全局状态管理
> 使用 pinia
# axios 封装
> src/service
- 灵活的拦截器;
- 可以创建多个实例,灵活根据项目进行调整;
- 每个实例,或者说每个接口都可以灵活配置请求头、超时时间等;
- 取消请求(可以根据 url 取消单个请求也可以取消全部请求)。

1
package.json

@ -9,6 +9,7 @@
"preview": "vite preview" "preview": "vite preview"
}, },
"dependencies": { "dependencies": {
"axios": "^1.3.4",
"pinia": "^2.0.32", "pinia": "^2.0.32",
"vue": "^3.2.45", "vue": "^3.2.45",
"vue-router": "^4.0.13" "vue-router": "^4.0.13"

17
src/api/index.js

@ -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
},
},
})
}

6
src/components/Count.vue

@ -13,7 +13,8 @@
</div> </div>
</template> </template>
<script setup> <script setup>
import { computed } from 'vue'
import { computed, onMounted } from 'vue'
import { get15DaysWeatherByArea } from '@/api'
import { useCountStore } from '@/store' import { useCountStore } from '@/store'
import { storeToRefs } from 'pinia' import { storeToRefs } from 'pinia'
const countStore = useCountStore() const countStore = useCountStore()
@ -21,5 +22,8 @@ const countStore = useCountStore()
const countComputed = computed(() => countStore.count) const countComputed = computed(() => countStore.count)
// storeToRefs api // storeToRefs api
const { doubleCount } = storeToRefs(countStore) const { doubleCount } = storeToRefs(countStore)
onMounted(() => {
get15DaysWeatherByArea()
})
</script> </script>
<style scoped></style> <style scoped></style>

38
src/service/index.js

@ -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

132
src/service/request.js

@ -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

57
yarn.lock

@ -217,11 +217,37 @@
resolved "https://registry.yarnpkg.com/@vue/shared/-/shared-3.2.47.tgz#e597ef75086c6e896ff5478a6bfc0a7aa4bbd14c" resolved "https://registry.yarnpkg.com/@vue/shared/-/shared-3.2.47.tgz#e597ef75086c6e896ff5478a6bfc0a7aa4bbd14c"
integrity sha512-BHGyyGN3Q97EZx0taMQ+OLNuZcW3d37ZEVmEAyeoA9ERdGvm9Irc/0Fua8SNyOtV1w6BS4q25wbMzJujO9HIfQ== integrity sha512-BHGyyGN3Q97EZx0taMQ+OLNuZcW3d37ZEVmEAyeoA9ERdGvm9Irc/0Fua8SNyOtV1w6BS4q25wbMzJujO9HIfQ==
asynckit@^0.4.0:
version "0.4.0"
resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==
axios@^1.3.4:
version "1.3.4"
resolved "https://registry.yarnpkg.com/axios/-/axios-1.3.4.tgz#f5760cefd9cfb51fd2481acf88c05f67c4523024"
integrity sha512-toYm+Bsyl6VC5wSkfkbbNB6ROv7KY93PEBBL6xyDczaIHasAiv4wPqQ/c4RjoQzipxRD2W5g21cOqQulZ7rHwQ==
dependencies:
follow-redirects "^1.15.0"
form-data "^4.0.0"
proxy-from-env "^1.1.0"
combined-stream@^1.0.8:
version "1.0.8"
resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f"
integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==
dependencies:
delayed-stream "~1.0.0"
csstype@^2.6.8: csstype@^2.6.8:
version "2.6.21" version "2.6.21"
resolved "https://registry.yarnpkg.com/csstype/-/csstype-2.6.21.tgz#2efb85b7cc55c80017c66a5ad7cbd931fda3a90e" resolved "https://registry.yarnpkg.com/csstype/-/csstype-2.6.21.tgz#2efb85b7cc55c80017c66a5ad7cbd931fda3a90e"
integrity sha512-Z1PhmomIfypOpoMjRQB70jfvy/wxT50qW08YXO5lMIJkrdq4yOTR+AW7FqutScmB9NkLwxo+jU+kZLbofZZq/w== integrity sha512-Z1PhmomIfypOpoMjRQB70jfvy/wxT50qW08YXO5lMIJkrdq4yOTR+AW7FqutScmB9NkLwxo+jU+kZLbofZZq/w==
delayed-stream@~1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619"
integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==
esbuild@^0.16.14: esbuild@^0.16.14:
version "0.16.17" version "0.16.17"
resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.16.17.tgz#fc2c3914c57ee750635fee71b89f615f25065259" resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.16.17.tgz#fc2c3914c57ee750635fee71b89f615f25065259"
@ -255,6 +281,20 @@ estree-walker@^2.0.2:
resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-2.0.2.tgz#52f010178c2a4c117a7757cfe942adb7d2da4cac" resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-2.0.2.tgz#52f010178c2a4c117a7757cfe942adb7d2da4cac"
integrity sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w== integrity sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==
follow-redirects@^1.15.0:
version "1.15.2"
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.2.tgz#b460864144ba63f2681096f274c4e57026da2c13"
integrity sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==
form-data@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452"
integrity sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==
dependencies:
asynckit "^0.4.0"
combined-stream "^1.0.8"
mime-types "^2.1.12"
fsevents@~2.3.2: fsevents@~2.3.2:
version "2.3.2" version "2.3.2"
resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a"
@ -286,6 +326,18 @@ magic-string@^0.25.7:
dependencies: dependencies:
sourcemap-codec "^1.4.8" sourcemap-codec "^1.4.8"
mime-db@1.52.0:
version "1.52.0"
resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70"
integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==
mime-types@^2.1.12:
version "2.1.35"
resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a"
integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==
dependencies:
mime-db "1.52.0"
nanoid@^3.3.4: nanoid@^3.3.4:
version "3.3.4" version "3.3.4"
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.4.tgz#730b67e3cd09e2deacf03c027c81c9d9dbc5e8ab" resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.4.tgz#730b67e3cd09e2deacf03c027c81c9d9dbc5e8ab"
@ -318,6 +370,11 @@ postcss@^8.1.10, postcss@^8.4.21:
picocolors "^1.0.0" picocolors "^1.0.0"
source-map-js "^1.0.2" source-map-js "^1.0.2"
proxy-from-env@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2"
integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==
resolve@^1.22.1: resolve@^1.22.1:
version "1.22.1" version "1.22.1"
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.1.tgz#27cb2ebb53f91abb49470a928bba7558066ac177" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.1.tgz#27cb2ebb53f91abb49470a928bba7558066ac177"

Loading…
Cancel
Save