mrr.sj.front/utils/request.js

333 lines
7.1 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import {
getToken,
setToken,
removeToken
} from './auth'
import {
setVersion
} from '../utils/version.js'
import {
getBaseUrl
} from '../utils/version.js'
let baseURL;
setVersion()
let isRefreshing = false
let subscribers = []
// 订阅 Token 刷新
function subscribeTokenRefresh(cb) {
subscribers.push(cb)
}
// 发布 Token 刷新完成
function onRrefreshed(token) {
subscribers.forEach(cb => cb(token))
subscribers = []
}
// 请求拦截器
const requestInterceptor = (options) => {
// 获取token
const token = uni.getStorageSync('accessToken')
if (token) {
options.header = {
...options.header,
'Authorization': `Bearer ${token}`
}
}
// #ifdef H5
// H5端跨域处理
options.header = {
...options.header,
'Access-Control-Allow-Origin': '*'
}
// #endif
return options
}
// 响应拦截器
const responseInterceptor = async (options, response, resolve, reject) => {
const {
statusCode,
data
} = response
// 请求成功
if (statusCode >= 200 && statusCode < 300) {
return data
}
// 处理错误
if (statusCode === 401) {
return await handleUnauthorized(options, resolve, reject)
}
// 其他错误
uni.showToast({
title: data.message || '请求失败',
icon: 'none'
})
return Promise.reject(data)
}
// 创建 uni.request 的封装
// const request = (options) => {
// return new Promise((resolve, reject) => {
// uni.request({
// ...options,
// success: (res) => {
// if (res.statusCode === 401) {
// // 处理 401 逻辑
// handleUnauthorized(options, resolve, reject)
// } else {
// resolve(res)
// }
// },
// fail: (err) => {
// reject(err)
// }
// })
// })
// }
// 请求方法
const request = async (options, isUpdate) => {
// 合并配置
let url = uni.getStorageSync('baseUrl')
if (uni.getStorageSync('setVersion').VersionCode == '') {
setVersion()
}
if (!url) {
await new Promise((resolve, reject) => {
uni.request({
url: 'https://api.mrrwlkj.top/api/openPuc/getSjApiUrl', // 接口地址
method: 'GET', // 请求方法(默认 GET
header: {
'Content-Type': 'application/json', // 请求头
'VersionCode': uni.getStorageSync('setVersion').VersionCode,
'DeviceBrand': uni.getStorageSync('setVersion').DeviceBrand,
'DeviceType': uni.getStorageSync('setVersion').DeviceType
},
success: (res) => {
if (res.data.code == 200) {
uni.setStorageSync('baseUrl', res.data.data.url)
url = res.data.data.url
resolve(url)
}
console.log('请求成功', res.data);
},
fail: (err) => {
console.log('请求失败', err);
},
complete: () => {
console.log('请求完成(无论成功失败都会执行)');
}
});
})
}
if (process.env.NODE_ENV === 'development') {
baseURL = url; // 发布到生产环境时,此处代码会被摇树移除掉。
baseURL = 'http://60.247.146.5:93'; // 发布到生产环境时,此处代码会被摇树移除掉。
//baseURL = 'http://60.247.146.5:96'; // 发布到生产环境时,此处代码会被摇树移除掉。
//baseURL = 'https://app.mrrweb.com.cn';
} else {
baseURL = url; // 发布到生产环境时,此处代码会被摇树移除掉。
baseURL = 'http://60.247.146.5:93'; // 发布到生产环境时,此处代码会被摇树移除掉。
//baseURL = 'http://60.247.146.5:96'; // 发布到生产环境时,此处代码会被摇树移除掉。
//baseURL = 'https://app.mrrweb.com.cn';
console.log('生产环境');
}
// 基础配置
const config = {
baseURL: baseURL, // APP和H5的开发URL
baseURL: baseURL, // APP和H5的开发URL
// baseURL: 'https://app.mrrweb.com.cn', // APP和H5的生产URL
header: {
'content-type': 'application/json',
'VersionCode': uni.getStorageSync('setVersion').VersionCode,
'DeviceBrand': uni.getStorageSync('setVersion').DeviceBrand,
'DeviceType': uni.getStorageSync('setVersion').DeviceType
},
timeout: 60000 // 超时时间
}
options = {
...config,
...options,
url: !isUpdate ? `${config.baseURL}${options.url}` : options.url
}
// 请求拦截
options = requestInterceptor(options)
// 发起请求
return new Promise((resolve, reject) => {
// #ifdef H5
// H5端添加loading
if (!options.hideLoading) {
uni.showLoading({
title: '加载中...'
})
}
// #endif
uni.request({
...options,
success: (res) => {
// #ifdef H5
if (!options.hideLoading) {
uni.hideLoading()
}
// #endif
resolve(responseInterceptor(options, res, resolve, reject))
},
fail: (err) => {
// #ifdef H5
if (!options.hideLoading) {
uni.hideLoading()
}
// #endif
// 网络错误处理
let errorMsg = '网络错误,请稍后重试'
// #ifdef H5
if (err.errMsg.includes('timeout')) {
errorMsg = '请求超时,请检查网络'
}
// #endif
uni.showToast({
title: errorMsg,
icon: 'none'
})
reject(err)
}
})
})
}
// 处理 401 未授权
async function handleUnauthorized(originalRequest, resolve, reject) {
if (!getToken()) {
return redirectToLogin()
}
// 如果正在刷新 Token将请求加入队列
if (isRefreshing) {
return subscribeTokenRefresh(token => {
originalRequest.header['Authorization'] = `Bearer ${token}`
request(originalRequest, true).then(resolve).catch(reject)
})
}
isRefreshing = true
try {
const newToken = await refreshToken()
setToken(newToken)
onRrefreshed(newToken)
// 用新 Token 重试原始请求
originalRequest.header['Authorization'] = `Bearer ${newToken}`
const response = await request(originalRequest, true)
// resolve(response)
return response
} catch (error) {
removeToken()
redirectToLogin()
// reject(error)
return error
} finally {
isRefreshing = false
}
}
// 刷新 Token
async function refreshToken() {
const refreshToken = uni.getStorageSync('refreshToken')
if (!refreshToken) {
throw new Error('No refresh token')
}
const res = await request({
url: '/sj/refreshtoken',
data: {
refresh_token: uni.getStorageSync('refreshToken'),
deviceid: getApp().globalData.deviceid
},
method: 'POST'
})
if (res.state == 1 || res.code == 200) {
uni.setStorageSync('accessToken', res.access_token)
uni.setStorageSync('refreshToken', res.refresh_token)
return res.access_token
}
throw new Error('Refresh token failed')
}
// 跳转到登录页
function redirectToLogin() {
// uni.reLaunch({
// url: '/pages/login/login'
// })
//一键登录测试
// uni.oprPresentLogin()
uni.navigateTo({
url: '/pages/blogPopup/blogPopup'
});
}
// 导出请求方法
export default {
// GET请求
get(url, data = {}, options = {}) {
return request({
url,
data,
method: 'GET',
...options
})
},
// POST请求
post(url, data = {}, options = {}) {
return request({
url,
data,
method: 'POST',
...options
})
},
// PUT请求
put(url, data = {}, options = {}) {
return request({
url,
data,
method: 'PUT',
...options
})
},
// DELETE请求
delete(url, data = {}, options = {}) {
return request({
url,
data,
method: 'DELETE',
...options
})
}
}