配置请求地址: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. linux全新机器环境搭建流程梳理

    软件解压后安装基础指令(复制用):./configure && make && make install ./configure --prefix=/usr/local ...

  2. 【大数据面试】【框架】kafka:组成、台数/参数配置、持久化、ISR队列、宕机、丢数据、重复数据、数据积压、优化各种配置(刷盘、存盘、副本、压缩)、zk、其他

    一.基本信息 1.组成 生产者 broker 消费者 zookeeper:brokerid.consumer信息(不包含生产者的信息) 2.需要安装多少台 2 * (生产者的峰值生产速率 * 副本 / ...

  3. 大规模爬取(新浪为例子)网页之downloader、parser的封装(涉及编码等细节)

    import requests import cchardet import traceback from lxml import etree def downloader(url,timeout = ...

  4. Python Excel 处理模块 : OpenPyXL

    OpenPyXL模块使用方法 以下是介绍OpenPyXL的基本使用,不涉及样式和合并单元格的跨行操作 一般来说,对于大名鼎鼎的xlrd,xlwt和xlutils三个模块,Excel操作有3个基本状态 ...

  5. webShell攻击及防御

    最近公司项目也是经常被同行攻击,经过排查,基本定位都是挂马脚本导致,所以针对webShell攻击做一下记录. 首先简单说下 什么是webShell? 利用文件上传,上传了非法可以执行代码到服务器,然后 ...

  6. 实用!7个强大的Python机器学习库!⛵

    作者:韩信子@ShowMeAI 机器学习实战系列:https://www.showmeai.tech/tutorials/41 本文地址:https://www.showmeai.tech/artic ...

  7. CH9434-MCU代码移植,芯片使用详细说明(附Linux开发资料链接)

    简介 CH9434是一款SPI转四串口转接芯片,提供四组全双工的9线异步串口,用于单片机/嵌入式/安卓系统扩展异步串口.提供25路GPIO,以及支持RS485收发控制引脚TNOW.本篇基于STM32F ...

  8. asp+vb.net解决调接口返回中文乱码问题

    1.问题描述 涉及语言:vb,vbscript,vb.net,asp 最近在工作中碰到了这样一个问题:需要调用一个接口解析简历文件中的关键信息.直接用postman测试该接口,接口返回值没问题,但一旦 ...

  9. [常用工具] cvat安装与使用指北

    cvat是一个非常好用的标注工具,但是也是非常难以安装的标注工具,所以本文简单讲一讲如何安装与使用cvat.cvat最好在ubuntu18.04安装,windows平台安装难度很大,然后在其他平台使用 ...

  10. java RSA加密

    参考了下面这个博主的文章,很有收获,简单处理后记录一下 RSA加密.解密.签名.验签的原理及方法 - PC君 - 博客园 工具类自带生成秘钥的方法,也可以用第三方工具生成秘钥 package com. ...