Skip to content

Commit a2b31eb

Browse files
committed
两个版本的网络请求库
1 parent f403af2 commit a2b31eb

File tree

185 files changed

+31091
-44
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

185 files changed

+31091
-44
lines changed

uniapp/common/code.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
/**
2+
* code 状态码
3+
*/
4+
5+
6+
7+
export const ACCESS_TOKEN_EXP = 4001 // access token 过期
8+
9+
export const REFRESH_TOKEN_EXP = 4002 // refresh token过期

uniapp/common/config.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
export const baseApi = 'https://www.fastmock.site'
2+
3+
export const baseApiPrefix = '/mock/26243bdf9062eeae2848fc67603bda2d/luchrequest'
4+
5+
export const baseApiFull = `${baseApi}${baseApiPrefix}`

uniapp/common/getAccessToken.js

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import Request from '@/utils/luch-request/index.js'
2+
import {
3+
baseApiFull
4+
} from '@/common/config.js'
5+
import userMessage from '@/store/userMessage.js'
6+
import {
7+
tokenExpMilli
8+
} from '@/common/mockVariable.js'
9+
const refreshRequest = new Request()
10+
refreshRequest.setConfig((config) => { /* 设置全局配置 */
11+
config.baseURL = baseApiFull /* 根域名不同 */
12+
return config
13+
})
14+
15+
let lock = false
16+
let promiseResult = []
17+
export function getAccessToken() {
18+
return new Promise((resolve, reject) => {
19+
promiseResult.push({
20+
resolve,
21+
reject
22+
})
23+
if (!lock) {
24+
lock = true
25+
refreshRequest.post('/api/get/accesstoken', {
26+
status: 'success', // 正式情况下不需要传这个,我这里为了模拟请求accesstoken的状态
27+
refreshToken: userMessage.state.refreshToken,
28+
expiresTime: tokenExpMilli // 正式情况下不需要传这个,我这里为了模拟{tokenExpMilli}毫秒后accessToken过期
29+
}).then(res => {
30+
let {code, data} = res.data
31+
if (code === 200) {
32+
userMessage.setTokenExpiresTime(data.expiresTime) // 更新accessToken过期时间
33+
userMessage.setAccessToken(data.accessToken) // 更新accessToken
34+
}
35+
while (promiseResult.length) {
36+
// p1.resolve(res.data)
37+
promiseResult.shift().resolve(res.data)
38+
}
39+
lock = false
40+
}).catch(err => {
41+
while (promiseResult.length) {
42+
// p1.reject(err)
43+
promiseResult.shift().reject(err)
44+
}
45+
lock = false
46+
})
47+
}
48+
})
49+
}

uniapp/common/mockVariable.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
/**
2+
* 模拟使用的变量
3+
*/
4+
5+
6+
export const tokenExpMilli = 5 * 60 * 1000; // accessToken 的有效时间。单位毫秒;5分钟

uniapp/common/service.js

Lines changed: 200 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,200 @@
1+
/**
2+
* @version 3.0.4
3+
* @Author lu-ch
4+
* @Email webwork.s@qq.com
5+
* 文档: https://www.quanzhan.co/luch-request/
6+
* github: https://github.com/lei-mu/luch-request
7+
* DCloud: http://ext.dcloud.net.cn/plugin?id=392
8+
* HBuilderX: beat-2.7.14 alpha-2.8.0
9+
*/
10+
import Request from '@/utils/luch-request/index.js'
11+
import userMessage from '@/store/userMessage.js'
12+
import {
13+
baseApiFull
14+
} from '@/common/config.js'
15+
import {
16+
getAccessToken
17+
} from '@/common/getAccessToken.js'
18+
import {
19+
ACCESS_TOKEN_EXP,
20+
REFRESH_TOKEN_EXP
21+
} from '@/common/code.js'
22+
import {
23+
debounce,
24+
openSystemSettings
25+
} from '@/utils/myUtils.js'
26+
import {
27+
RESPONSE_TEST
28+
} from '@/common/storageTypes.js'
29+
let expireTokenCache = [] // 储存过期的token
30+
const ACCESS_TOKEN_FILEDS = 'accessToken' // header 里传accessToken的键名
31+
const http = new Request()
32+
http.setConfig((config) => { /* 设置全局配置 */
33+
config.baseURL = baseApiFull /* 根域名不同 */
34+
config.custom = {
35+
auth: true // 是否传递accesstoken
36+
}
37+
return config
38+
})
39+
40+
41+
42+
http.interceptors.request.use(async (config) => { /* 请求之前拦截器。可以使用async await 做异步操作 */
43+
config.header = {
44+
...config.header,
45+
}
46+
if (config.custom.auth) {
47+
// 必须在这里就先赋值,避免accessToken 等于undefined 的情况
48+
config.header[ACCESS_TOKEN_FILEDS] = userMessage.state.accessToken
49+
// 请确保refreshToken存在。refreshToken不存在的情况自行处理
50+
if (!userMessage.state.accessToken || Date.now() > userMessage.state.expiresTime) {
51+
52+
// responseTest !== true:这里为了模拟reponse 拦截获取新的accessToken。正常情况下没有这个判断
53+
let responseTest = uni.getStorageSync(RESPONSE_TEST)
54+
console.log(responseTest);
55+
if (responseTest !== true) { // 关闭requet 拦截重新获取accesstoekn 功能。模拟用。
56+
console.log('全局拦截器 request:accessToken 过期或不存在,调起重新获取');
57+
try {
58+
const {
59+
data,
60+
code
61+
} = await getAccessToken()
62+
console.log('全局拦截器 request:重新获取accessToken后code');
63+
console.log(code);
64+
console.log('全局拦截器 request:重新获取accessToken后data');
65+
console.log(data);
66+
if (code === 200) {
67+
expireTokenCache = []
68+
config.header[ACCESS_TOKEN_FILEDS] = data.accessToken
69+
} else {
70+
// 其他情况,可能refreshToken过期了等等,请根据自身逻辑处理
71+
}
72+
} catch (e) {
73+
console.log(e);
74+
// 可能由于网络原因通过refreshToken 获取accessToken失败了;可以根据自身逻辑处理,我这里直接放弃本次请求,会进入interceptors.response的错误拦截函数
75+
return Promise.reject(config)
76+
}
77+
}
78+
}
79+
}
80+
81+
return config
82+
}, (config) => {
83+
return Promise.reject(config)
84+
})
85+
86+
/**
87+
* 这里我使用了自己的debounce函数,实际项目中我推荐使用loadsh 的debounce函数。当然使用自己debounce函数也没什么问题
88+
*/
89+
const reLaunchLogin = debounce(function(mes) {
90+
console.log('全局拦截,重新登录');
91+
userMessage.clearMessageSync()
92+
uni.showToast({
93+
icon: 'none',
94+
title: mes,
95+
duration: 2100
96+
})
97+
uni.reLaunch({
98+
url: '/pages/login/login'
99+
})
100+
}, 1000, true)
101+
const requestInterResErr = debounce(function() {
102+
uni.getNetworkType({
103+
success: (netRes) => {
104+
if (netRes.networkType == "none") {
105+
uni.showModal({
106+
title: '提示',
107+
content: '暂无网络,是否去设置?',
108+
confirmText: '去设置',
109+
success(modalRes) {
110+
if (modalRes.confirm) {
111+
/**
112+
* iOS App第一次安装启动后,会弹出是否允许联网的询问框,在用户点击同意前,调用联网API会失败
113+
*/
114+
openSystemSettings();
115+
}
116+
}
117+
})
118+
}
119+
}
120+
});
121+
}, 3000, true)
122+
123+
/**
124+
* 避免进入死循环,重新new一个用于重新发起请求的实例
125+
*/
126+
const againHttp = new Request({
127+
baseURL: baseApiFull
128+
})
129+
130+
againHttp.interceptors.request.use(config => {
131+
config.header[ACCESS_TOKEN_FILEDS] = userMessage.state.accessToken
132+
return config
133+
}, error => {
134+
return Promise.reject(error)
135+
})
136+
137+
// 必须使用异步函数,注意
138+
http.interceptors.response.use(async (response) => { /* 请求之后拦截器。*/
139+
const serviceCode = response.data.code // 服务端code
140+
141+
if (serviceCode === ACCESS_TOKEN_EXP) {
142+
// accessToken 过期了。
143+
let accessToken = response.config.header[ACCESS_TOKEN_FILEDS]
144+
expireTokenCache.push(accessToken)
145+
// 说明本地的accessToken已经过期了.
146+
// typeof accessToken === 'undefined' 是说明这个接口需要传{ACCESS_TOKEN_FILEDS}但是你却没有传。会重新传入发起请求
147+
if (expireTokenCache.includes(userMessage.state.accessToken)) {
148+
try {
149+
const {
150+
data,
151+
code
152+
} = await getAccessToken()
153+
console.log('全局拦截器 response:重新获取accessToken后code');
154+
console.log(code);
155+
console.log('全局拦截器 response:重新获取accessToken后data');
156+
console.log(data);
157+
if (code === 200) {
158+
// return Promise.resolve(againHttp.middleware(response.config))
159+
try {
160+
const localResponse = await againHttp.middleware(response.config)
161+
return localResponse
162+
} catch (e) {
163+
// 重新获取数据可能因为网络原因获取失败了
164+
return Promise.reject(e)
165+
}
166+
} else {
167+
// 其他情况,可能refreshToken过期了等等,请根据自身逻辑处理
168+
}
169+
} catch (e) {
170+
console.log(e);
171+
// 可能由于网络原因通过refreshToken 获取accessToken失败了;可以根据自身逻辑处理,我这里直接放弃本次请求,会进入catch
172+
return Promise.reject(response)
173+
}
174+
} else {
175+
// 本地的accessToken就是新的,重新发起请求
176+
console.log('本地的accessToken就是新的,重新发起请求');
177+
try {
178+
const localResponse = await againHttp.middleware(response.config)
179+
return response
180+
} catch (e) {
181+
// 重新获取数据可能因为网络原因获取失败了
182+
return Promise.reject(e)
183+
}
184+
}
185+
186+
} else if (serviceCode === REFRESH_TOKEN_EXP) {
187+
// refreshToken 过期了
188+
reLaunchLogin('请重新登录!')
189+
}
190+
console.log(serviceCode);
191+
return response
192+
}, (response) => { // 请求错误做点什么。可以使用async await 做异步操作
193+
console.log(response)
194+
requestInterResErr()
195+
return Promise.reject(response)
196+
})
197+
198+
export {
199+
http
200+
}

uniapp/common/storageTypes.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
/**
2+
* 本地储存键 types
3+
* **/
4+
5+
const keys = 'm_' // 命名空间
6+
7+
export const USERINFO = `${keys}user_info`; // userinfo object
8+
export const ACCESS_TOKEN = `${keys}access_token`; // access token
9+
export const REFRESH_TOKEN = `${keys}refresh_token`; // refresh token
10+
export const TOKEN_EXP_TIME = `${keys}token_exp_time`; // access token 过期时间 13位时间戳
11+
12+
13+
export const RESPONSE_TEST = `${keys}response_test`; // 用户测试是否关闭request 拦截获取新的access_token; mock用
14+

uniapp/main.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,17 @@ import App from './App'
22
import Vue from 'vue'
33
import uView from "uview-ui"
44
import store from '@/store';
5+
import { http } from '@/common/service.js' // 全局挂载引入,配置相关在该index.js文件里修改
6+
57
Vue.use(uView);
68

79
// 引入uView提供的对vuex的简写法文件
810
let vuexStore = require('@/store/$u.mixin.js');
911
Vue.mixin(vuexStore);
1012

1113

14+
Vue.prototype.$http = http
15+
1216
Vue.config.productionTip = false
1317
App.mpType = 'app'
1418
const app = new Vue({

uniapp/pages.json

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,42 @@
77
{
88
"path": "pages/index/index",
99
"style": {
10-
"navigationBarTitleText": "uni-app"
10+
"navigationBarTitleText": "luch-request"
1111
}
12+
}, {
13+
"path": "pages/login/login",
14+
"style": {}
15+
}, {
16+
"path": "pages/user/user",
17+
"style": {}
18+
}, {
19+
"path": "pages/concurrent/concurrent",
20+
"style": {}
21+
}
22+
,{
23+
"path" : "pages/concurrent2/concurrent2",
24+
"style" : {}
1225
}
1326
],
1427
"globalStyle": {
1528
"navigationBarTextStyle": "black",
1629
"navigationBarTitleText": "uni-app",
1730
"navigationBarBackgroundColor": "#F8F8F8",
1831
"backgroundColor": "#F8F8F8"
32+
},
33+
"tabBar": {
34+
"list": [{
35+
"pagePath": "pages/index/index",
36+
"iconPath": "static/logo.png",
37+
"selectedIconPath": "static/logo.png",
38+
"text": "首页"
39+
},
40+
{
41+
"pagePath": "pages/user/user",
42+
"iconPath": "static/logo.png",
43+
"selectedIconPath": "static/logo.png",
44+
"text": "我的"
45+
}
46+
]
1947
}
2048
}

0 commit comments

Comments
 (0)