配置请求地址:config->index.js

一个项目里通常有一个config->index.js,该文件包含了当前项目的请求地址,以及项目的版本信息。

// 请求地址
const API_URL_DEV = 'http://xxx.xxx.xxx.net:81/xxx' // 测试接口
const API_URL_TRIAL = 'http://xxx.xxx.xxx.net:81/xxx' // 体验版接口
const API_URL_PROD = 'http://xxx.xxx.xxx.net:81/xxx' // 线上接口

上面就是api请求的baseUrl,在后续配置axios的时候会用到,在项目开发中,有时候会切换开发版和体验版,就是更改此处的地址。

微信小程序里需要区分一件事,那就是当前的运行环境,是否是开发环境。

微信小程序官方提供了 wx.getAccountInfoSync()可以获取小程序版本的appid以及小程序的版本信息,根据envVersion来判断当前小程序是线下环境还是线上环境。

  let {
miniProgram: {
envVersion,
version
}
} = wx.getAccountInfoSync() // 获取小程序版本信息

将获取版本信息的操作封装成一个函数,根据运行环境配置小程序版本信息和apiUrl

function getparamsByEnv() {
/**
* 官方提供:wx.getAccountInfoSync()获取小程序版本信息,以及appid
* 模拟当前环境
* 线下的是 'develop' 线上是 'prod'
*/ let {
miniProgram: {
envVersion,
version
}
} = wx.getAccountInfoSync() // 获取小程序版本信息 // 返回的参数
let params = {
apiUrl: '',
version: version,
tester: true
} switch (envVersion) {
case 'develop':
params.apiUrl = API_URL_DEV // 此处对应上面配置的线下baseUrl接口
params.version = '1.0.2'
break
case 'trial':
params.apiUrl = API_URL_TRIAL // 此处对应上面配置的体验版baseUrl接口
params.version = '1.0.2'
break
default:
params.apiUrl = API_URL_PROD // 此处对应上面配置的线上baseUrl接口
params.tester = false
break
}
return params // 配置完成后返回params
}

完整的config.js配置

// 请求地址
const API_URL_DEV = 'http://xxx.xxx.xxx.net:81/xxx' // 测试接口
const API_URL_TRIAL = 'http://xxx.xxx.xxx.net:81/xxx' // 体验版接口
const API_URL_PROD = 'http://xxx.xxx.xxx.net:81/xxx' // 线上接口 const envParams = getparamsByEnv() export default envParams.apiUrl // 导出apiUrl export const version = envParams.version // 导出版本信息 export const tester = envParams.tester // 导出tester /**
* 区分小程序当前运行环境
* @return {Boolean} 是否是开发环境
*/
function getparamsByEnv() {
/**
* 官方提供:wx.getAccountInfoSync()获取小程序版本信息,以及appid
* 模拟当前环境
* 线下的是 'develop' 线上是 'prod'
*/ let {
miniProgram: {
envVersion,
version
}
} = wx.getAccountInfoSync() // 获取小程序版本信息
let params = {
apiUrl: '',
version: version,
tester: true
}
switch (envVersion) {
case 'develop':
params.apiUrl = API_URL_DEV
params.version = '1.0.2'
break
case 'trial':
params.apiUrl = API_URL_TRIAL
params.version = '1.0.2'
break
default:
params.apiUrl = API_URL_PROD
params.tester = false
break
}
return params
}

配置request.js

在这个文件其实就是配置axios,需要引入axios以及上面配置的config.js文件

import axios from 'axios'
import mpAdapter from 'axios-miniprogram-adapter'
axios.defaults.adapter = mpAdapter
import API_URL from '../config/index' // apiUrl

axios有三个配置项,分别是:baseUrl请求拦截器响应拦截器,下面分别就这些配置项进行配置。

配置请求baseUrl

引入config.jsapiUrl,在axiosbaseUrl中配置

const service = axios.create({
baseURL: API_URL, // url = base url + request url
})

配置请求拦截器service.interceptors.request.use

在请求拦截器内通常会做一些配置,比如:在请求头中携带token,在请求的时候弹出“加载中”告诉用户正在发生什么等等,通常只要发送请求,都会经过请求拦截器。

let ajaxTimes = 0; // 状态
// 请求拦截器
service.interceptors.request.use(function (config) {
// config就是请求的配置信息,里面包含baseUrl地址,headers请求头,url请求接口等信息
// 在发送请求前,可以对config做一些配置操作(加盐) // 获取token
if(wx.getStorageSync('token')){
// 如果token存在,那么在请求头上带上token
config.headers['access_token'] = wx.getStorageSync('token')
} // 请求的时候,添加一个弹框,告诉用户正在发生什么
// config.url != 'xxx/xxx' 请求某个接口不弹出提示
if (!ajaxTimes++ && config.url != '/lottery/activity/get-prize'){
wx.showLoading({ title: '加载中···' }) // 其实把wx.showLoading写在请求拦截器里都会生效,这里只是做了一个ajaxTimes的判断,优化了提示弹框
} return config; // 返回配置信息-也就是请求头之类的 },function (error){
// 处理错误请求
return Promise.reject(error)
})

配置响应拦截器service.interceptors.response.use

只要请求接口,接口响应并返回,都会走响应拦截器,可以在响应拦截器内做一些配置,比如请求日志、token过期处理、账户封禁处理、服务器错误处理、响应成功处理等等。

// 添加响应拦截器
service.interceptors.response.use(function (response) {
// response返回上方请求拦截器的config配置信息,data后台接口返回的数据,headers服务器响应头等信息 // 由于微信小程序的 toast 和 loading 相关接口可以相互混用,所以需要取消混用提示,也是关联上方的“加载中”优化
if (ajaxTimes > 0 && --ajaxTimes === 0) {
wx.hideLoading({noConflict:true}) // // 取消混用提示
} // 这里返回的response.data就是后台接口返回的数据
const res = response.data
// 如果返回的code不是200或201,则判断为错误
if(res.code && res.code !== 200 && res.code !== 201){
// 分别对这些错误进行对应的处理 if(res.code === 1004){
// 1004状态码表示token过期,需要重新获取token,并在获取token后,重新请求接口,清除token
return reSetToken(response.config) // 这里调用获取token的方法,后面会进行配置 } else if(res.code === 9001){
// 返回9001状态码处理,通过wx.login获取code
if (res.message.indexOf('code been used') !== -1) {
getApp().globalData.userInfo._getLoginCode()
} else if (res.message.indexOf('invalid code') !== -1) {
console.log('invalid code')
}
return Promise.reject(res) } else if (res.code === 400 || res.code === 500){
// 返回400或500状态码,表示服务器错误或者接口请求异常
wx.showToast({title: `${res.message}`,icon: 'none'})
return Promise.reject(res) } else if(res.code == 30011){ // 账户封禁
// 返回30011状态码,表示该账号已封禁,如果想对封禁的账户做一些操作可以将返回的信息携带并跳转到封禁页,封禁页展示封禁的原有和信息,用户可以在封禁页做封禁申诉等操作
const info = res.message;
wx.reLaunch({
url: `/pages/account/index?info=${info}`,
})
} return Promise.reject(res) // 其他的错误状态码就直接reject
} else {
return res
}
}, function (error) {
// 处理响应错误
if (ajaxTimes > 0 && --ajaxTimes === 0) {
wx.hideLoading({noConflict:true})
}
return Promise.reject(error);
}

token过期后重新获取token,在响应拦截器里说过,返回状态1004表示token过期,在这里封装重新获取token的方法,在响应拦截器状态1004处调用。

let tokenLoad = false
// 重新获取token
function reSetToken(params) {
// 这里的params就是response.config的信息
return new Promise(async (resolve,reject) => {
// 用函数形式将resolve存入,等待刷新后再执行
const app = getApp() // 获取小程序全局唯一的 App 实例
if(!app){
return console.log("app undefined")
} wx.queue.asyncWait("login_back", () => {
service(params).then(res => {
resolve(res)
}, err => {
reject(err)
})
},params.url) // tokenLoad = true什么都不做,false走重新发起登录的流程
if(tokenLoad) {
console.log("中断重新获取token")
} else {
// 将tokenLoad状态更改为true
tokenLoad = true
try {
// 重新发起登录,调用发起登录的方法
app.globalData.userInfo.Login().then(res => {
if(res === 'notBindPhone') {
app.awaitLoginDialog('request')
}
tokenLoad = false // 登录成功后将tokenLoad改为false,等待下次token过期重新发起登录
}).catch(()=>{
tokenLoad = false
}) } catch (error) {
// 重新获取token报错,说明用户没注册,需要唤醒注册弹窗,如果在tabbar页面,就不自动唤醒
app.awaitLoginDialog('request')
tokenLoad = false
reject(error)
}
} })
}

完整的request.js配置

import axios from 'axios'
import mpAdapter from 'axios-miniprogram-adapter'
axios.defaults.adapter = mpAdapter
import API_URL from '../config/index'
const service = axios.create({
baseURL: API_URL, // url = base url + request url
}) let ajaxTimes = 0
// 请求拦截器
service.interceptors.request.use(function (config) {
// config是请求的配置信息,内部有baseUrl地址,headers请求头,url请求接口等信息
// console.log('请求拦截器',config); // 发送请求之前你可以在这里对config做一些配置
// 获取token
if (wx.getStorageSync('token')) {
// 如果token存在,那么在请求头上带上token
config.headers['access_token'] = wx.getStorageSync('token')
} // 请求的时候,添加一个弹框wx.showLoading告诉用户正在加载中
// !ajaxTimes++是因为请求可能不止一次,请求的时候这种"加载中"的提醒优化,其实只需要显示一次即可,所以需要做一个判断,ajaxTimes == 0的时候提示一次,后续ajaxTimes++都不会提示,每次进新页面或刷新都会重置ajaxTimes == 0 ,这里做的操作其实就是为了优化,减少提示的次数。
if (!ajaxTimes++ && config.url != '/lottery/activity/get-prize' && config.url != '/lottery/activity/time'){
wx.showLoading({ title: '加载中···' }) // 其实把wx.showLoading写在请求拦截器里都会生效,这里只是做了一个ajaxTimes的判断,优化了提示弹框
} return config;
}, function (error) {
// 处理请求错误
return Promise.reject(error);
}); // 添加一个响应拦截器
service.interceptors.response.use(function (response) {
// response返回请求拦截器的config配置信息,data后台接口返回的数据,headers服务器响应头等信息
// console.log('响应拦截器',response);
if (ajaxTimes > 0 && --ajaxTimes === 0) {
wx.hideLoading({noConflict:true})
} // 这里返回的response.data就是后台接口返回的数据
const res = response.data
console.log('请求日志:',response); // 请求日志
// 如果自定义代码不是200或201,则判断为错误.
if (res.code && res.code !== 200 && res.code !== 201 && res.code !== 2001 && res.code !== 2002) {
if (res.code === 1004) {
// 1004状态码表示token过期,这是需要重新获取token,并且在获取完token之后,重新请求接口,清除token
return reSetToken(response.config)
} else if (res.code === 9001) {
if (res.message.indexOf('code been used') !== -1) {
getApp().globalData.userInfo._getLoginCode()
} else if (res.message.indexOf('invalid code') !== -1) {
console.log('invalid code')
}
return Promise.reject(res)
} else if (res.code === 400 || res.code === 500) {
wx.showToast({title: `${res.message}`,icon: 'none'})
return Promise.reject(res)
} else if (res.code === 30011) { // 账户封禁
const info = res.message;
// 根据code判断该账户是否封禁,如果封禁,则携带信息跳转到封禁页
wx.reLaunch({
url: `/pages/account/index?info=${info}`,
})
}
return Promise.reject(res)
} else {
return res
}
}, function (error) {
// 处理响应错误
if (ajaxTimes > 0 && --ajaxTimes === 0) {
wx.hideLoading({noConflict:true})
}
return Promise.reject(error);
}); let tokenLoad = false
// 重新获取token
function reSetToken(params) {
// console.log('重新获取token:',params);
return new Promise(async (resolve, reject) => {
// 用函数形式将 resolve 存入,等待刷新后再执行
const app = getApp()
if (!app) {
console.error("app undefind");
return
}
wx.queue.asyncWait("login_back", () => {
service(params).then(res => {
resolve(res)
}, err => {
reject(err)
})
},params.url) // true什么都不做,false走重新发起登录流程
if (tokenLoad) {
console.log("中断重新获取token");
} else {
// 将tokenLoad状态更改为true
tokenLoad = true
try {
// 重新发起登录
app.globalData.userInfo.Login().then(res => {
// console.log('发起登录',res);
if (res === 'notBindPhone') {
app.awaitLoginDialog('request')
}
tokenLoad = false // 登录成功后将tokenLoad改为false,等待下次token过期重新发起登录
}).catch(() => {
tokenLoad = false
})
} catch (error) {
// 重新获取token报错,说明用户没有注册。需要唤起注册弹窗,如果是在tabbar页面,就不自动唤起
// console.log(error, '请求token失败报错')
app.awaitLoginDialog('request')
tokenLoad = false
reject(error)
}
}
}) }
export default service

getApp()为微信小程序的全局唯一App实例,用户的登录方法可以挂载到App实例当中,在需要唤醒登录处获取getApp()中挂载的登录方法即可唤醒登录。

配置项目请求地址和axios以及实现token过期无痛刷新的更多相关文章

  1. token回话保持,axios请求拦截和导航守卫以及token过期处理

    1:了解token:有时候大家又说token令牌.整个机制是前端第一次登陆发送请求,后端会根据前端的用户名和密码, 通过一些列的算法的到一个token令牌, 这个令牌是独一无二的,前端每次发送请求都需 ...

  2. vue中main.js配置后端请求地址

    Vue.config.productionTip = false; axios.defaults.baseURL = 'http://127.0.0.1:8003/';//后端开发环境地址 // ax ...

  3. net core体系-web应用程序-4net core2.0大白话带你入门-4asp.net core配置项目访问地址

    asp.net core配置访问地址  .net core web程序,默认使用kestrel作为web服务器. 配置Kestrel Urls有四种方式,我这里只介绍一种.其它方式可自行百度. 在Pr ...

  4. vue3.0 配置公共请求地址

    正常请求接口: return request({ url: 'http://192.168.1.0/User/cancelUpgrade', method: 'get', params: data } ...

  5. 请求时token过期自动刷新token

    1.在开发过程中,我们都会接触到token,token的作用是什么呢?主要的作用就是为了安全,用户登陆时,服务器会随机生成一个有时效性的token,用户的每一次请求都需要携带上token,证明其请求的 ...

  6. 手把手,完整的从0搭建vite-vue3-ts项目框架:配置less+svg+pinia+vant+axios

    项目同步git:https://gitee.com/lixin_ajax/vue3-vite-ts-pinia-vant-less.git 为避免赘述,过于基础的点会直接省略或贴图,比如创建文件夹/文 ...

  7. Flutter用dio封装http网络请求,设置统一的请求地址、headers及处理返回内容

    封装http请求是项目中经常需要做的,常用于设置通用请求地址.请求headers以及处理返回结果,例如在项目中开发地址.测试地址.上线地址是不一样的,当在封装的请求设置好默认地址之后只需要改一个地址而 ...

  8. Retrofit Token过期 重新请求Token再去请求接口

    需求是这样的:请求接口A -- 服务器返回数据Token过期或失效  -- 重新请求Token并设置 -- 再去请求接口A 刚解决了这个问题,趁热打铁,写个博客记录一下:这个Token是添加到请求头里 ...

  9. 使用ajax请求接口,跨域后cookie无法设置,全局配置ajax;及使用axios跨域后cookie无法设置,全局配置axios

    问题一: 使用ajax/axios跨域请求接口,后端放行了,能够正常获取数据,但是cookie设置不进去,后端登录session判断失效 ajax解决办法: //设置ajax属性 crossDomai ...

  10. vue-cli项目接口地址可配置化(多环境部署)一处修改多处适用

    本文档目的在于帮助对vue了解比较少的同学,能够快速配置vue应用中的接口地址.方便项目切换服务环境后,重新修改多组件的http请求地址. 一.前言 我们在上一篇文章分享了vue-cli项目基本搭建( ...

随机推荐

  1. Springboot整合thymeleaf报错whitelabel page

    1.SpringBootApplication未放在最外层 2.application.properties未配置spring.thymeleaf.check-template-location=tr ...

  2. 【Hadoop学习】下:MapReduce程序编写、Hadoop序列化、框架原理、Yarn组件、设置队列

    一.MapReduce概述 1.定义 编程框架,组成分布式运算程序,运行在集群上 2.特点 优点:易于编程.扩展性.容错性(内部完成).海量数据离线处理 缺点:非实时.不擅长流式计算.不擅长DAG有向 ...

  3. m3u8文件后缀jpg,png等处理方法及视频合并

    处理 # 解析伪装成png的ts def resolve_ts(src_path, dst_path): ''' 如果m3u8返回的ts文件地址为 https://p1.eckwai.com/ufil ...

  4. Linux基础:ssh与scp

    登陆 登陆服务器 ssh user@hostname user: 用户名 hostname :IP地址或域名 第一次登陆会提示 The authenticity of host '123.57.47. ...

  5. Java基础篇——JVM初步

    1.JVM的位置 2.JVM体系结构 3.类加载器 虚拟机加载器(java) 启动类(根)加载器(C++) 扩展类加载器(java)↑ 应用程序加载器(java)↑ 4.双亲委派机制 类加载器收到类加 ...

  6. [WPF]创建系统栏小图标

    隐藏窗体任务栏图标 /// <summary> /// MainWindow.xaml 的交互逻辑 /// </summary> public partial class Ma ...

  7. [WPF]项目整合Metro和MaterialDesignInXamlToolkit UI框架

    项目地址 MapApps:Metro MaterialDesignInXamlToolkit:MaterialDesignInXamlToolkit MapApps官网:官网链接 官方整合文档 官方提 ...

  8. Java学习笔记:2022年1月6日(补充)

    Java学习笔记:2022年1月6日(补充) ​ 摘要:这篇笔记主要记录了2022年1月6日下午的笔记,主要内容为Java语言中的基础操作,以及基础知识点,了解这些后基本上就可以使用Java写算法了. ...

  9. Java基础学习笔记-流程控制

    Java程序结构 顺序结构 分支选择结构 循环结构 顺序结构 分支选择结构 if-else Switch case Switch case 注意点 要配合break,要不就会一直往下走 case 值必 ...

  10. 看不懂打我系列------图文并茂基于CentOS Linux release 7.8.2003 Core安装并Docker化你的Node.js应用

    @图文并茂基于CentOS Linux release 7.8.2003 Core安装并Docker化你的Node.js应用 简体中文 | English 说明 本文介绍如何在CentOS Linux ...