uni-app 使用uni.request封装发送api请求文档服务器请求导航守卫

前言

  • 刚刚接触uni-app时候想着直接使用axios发请求,可以发送成功但是请求头有点问题

  • 后面发现教程都是使用@escookrequest-miniprogram三方包发送请求-是没有问题

  • 为什么不直接用uni.request()发送请求,是因为每次请求都要写一次添加请求头不合理

  • 后面随着深入了解uni-app,发现开源框架,若依,芋道,都是封装一层uni.request发请求

  • 解决了统一添加请求头问题,使用uni.request比较合理,自己写可能不全面,可以直接搬

细节

1.观察我们会发现在utils工具文件夹下有upload.js和request.js2个文件在发请求是都在引入

2.request.js基于uni.request封装添加请求头,用户id。专门用来发送普通api请求

3.upload.js基于 uni.uploadFile封装添加请求头,用户id,专门用来对接文档服务器,上传图片文件

4.并不是所有接口都需要添加请求头,在不需要添加的请求头的接口写isToken: false,

代码实现

1.在utils工具文件夹下分别建立request.js和upload.js文件夹-代码如下

request.js

// 引入vuex-调用退出登录方法
import store from '@/store'
// 引入基地址文件
import config from '@/config'
// 引入获取token文件
import { getAccessToken } from '@/utils/auth'
// 引入转台码错误文件
import errorCode from '@/utils/errorCode'
// 引入公共方法文件
import { toast, showConfirm, tansParams } from '@/utils/common'
​
let timeout = 10000
const baseUrl = config.baseUrl;
​
const request = config => {// 是否需要设置 tokenconst isToken = (config.headers || {}).isToken === falseconfig.header = config.header || {}if (getAccessToken() && !isToken) {config.header['Authorization'] = 'Bearer ' + getAccessToken()}// 设置租户 TODO 芋艿:强制 1 先config.header['tenant-id'] = '1';// get请求映射params参数if (config.params) {let url = config.url + '?' + tansParams(config.params)url = url.slice(0, -1)config.url = url}return new Promise((resolve, reject) => {uni.request({method: config.method || 'get',timeout: config.timeout ||  timeout,url: config.baseUrl || baseUrl + config.url,data: config.data,// header: config.header,header: config.header,dataType: 'json'}).then(response => {let [error, res] = responseif (error) {toast('后端接口连接异常')reject('后端接口连接异常')return}const code = res.data.code || 200const msg = errorCode[code] || res.data.msg || errorCode['default']if (code === 401) {showConfirm('登录状态已过期,您可以继续留在该页面,或者重新登录?').then(res => {if (res.confirm) {store.dispatch('LogOut').then(res => {uni.reLaunch({ url: '/pages/login' })})}})reject('无效的会话,或者会话已过期,请重新登录。')} else if (code === 500) {toast(msg)reject('500')} else if (code !== 200) {toast(msg)reject(code)}resolve(res.data)}).catch(error => {let { message } = errorif (message === 'Network Error') {message = '后端接口连接异常'} else if (message.includes('timeout')) {message = '系统接口请求超时'} else if (message.includes('Request failed with status code')) {message = '系统接口' + message.substr(message.length - 3) + '异常'}toast(message)reject(error)})})
}
​
export default request

upload.js

// 引入vuex-调用退出登录方法
import store from '@/store'
// 引入基地址文件
import config from '@/config'
// 引入获取token文件
import { getAccessToken } from '@/utils/auth'
// 引入转台码错误文件
import errorCode from '@/utils/errorCode'
// 引入公共方法文件
import { toast, showConfirm, tansParams } from '@/utils/common'
​
let timeout = 10000
const baseUrl = config.baseUrl
​
const upload = config => {// 是否需要设置 tokenconst isToken = (config.headers || {}).isToken === falseconfig.header = config.header || {}if (getAccessToken() && !isToken) {config.header['Authorization'] = 'Bearer ' + getAccessToken()}// get请求映射params参数if (config.params) {let url = config.url + '?' + tansParams(config.params)url = url.slice(0, -1)config.url = url}// 设置租户 TODO 芋艿:强制 1 先config.header['tenant-id'] = '1';return new Promise((resolve, reject) => {uni.uploadFile({timeout: config.timeout || timeout,url: baseUrl + config.url,filePath: config.filePath,name: config.name || 'file',header: config.header,formData: config.formData,method: config.method || 'post',success: (res) => {let result = JSON.parse(res.data)const code = result.code || 200const msg = errorCode[code] || result.msg || errorCode['default']if (code === 200) {resolve(result)} else if (code == 401) {showConfirm("登录状态已过期,您可以继续留在该页面,或者重新登录?").then(res => {if (res.confirm) {store.dispatch('LogOut').then(res => {uni.reLaunch({ url: '/pages/login/login' })})}})reject('无效的会话,或者会话已过期,请重新登录。')} else if (code === 500) {toast(msg)reject('500')} else if (code !== 200) {toast(msg)reject(code)}},fail: (error) => {let { message } = errorif (message == 'Network Error') {message = '后端接口连接异常'} else if (message.includes('timeout')) {message = '系统接口请求超时'} else if (message.includes('Request failed with status code')) {message = '系统接口' + message.substr(message.length - 3) + '异常'}toast(message)reject(error)}})})
}
​
export default upload

2.在最外层与utils.js同级下创建基地址文件config.js

// 应用全局配置
module.exports = {baseUrl: '基地址',// 应用信息appInfo: {// 应用名称name: "app",// 应用版本version: "1.0.0",// 应用logologo: "/static/logo.png",// 官方网站site_url: "",// 政策协议agreements: [{title: "隐私政策",url: ""},{title: "用户服务协议",url: ""}]}
}

3.在utils.js工具文件下创建auth.js文件-存储token

RefreshTokenKey-是用来补救token失效换取token的一种无感刷新形式没有不用管

const AccessTokenKey = 'ACCESS_TOKEN'
const RefreshTokenKey = 'REFRESH_TOKEN'
​
// ========== Token 相关 ==========
​
export function getAccessToken() {return uni.getStorageSync(AccessTokenKey)
}
​
export function getRefreshToken() {return uni.getStorageSync(RefreshTokenKey)
}
​
export function setToken(token) {uni.setStorageSync(AccessTokenKey, token.accessToken)uni.setStorageSync(RefreshTokenKey, token.refreshToken)
}
​
export function removeToken() {uni.removeStorageSync(AccessTokenKey)uni.removeStorageSync(RefreshTokenKey)
}

4.在utils.js工具文件下创建errorCode.js文件-状态码错误文件

export default {'401': '认证失败,无法访问系统资源','403': '当前操作没有权限','404': '访问资源不存在','default': '系统未知错误,请反馈给管理员'
}

5.在utils.js工具文件下创建common.js文件-公共方法

/**
* 显示消息提示框
* @param content 提示的标题
*/
export function toast(content) {uni.showToast({icon: 'none',title: content})
}
​
/**
* 显示模态弹窗
* @param content 提示的标题
*/
export function showConfirm(content) {return new Promise((resolve, reject) => {uni.showModal({title: '提示',content: content,cancelText: '取消',confirmText: '确定',success: function(res) {resolve(res)}})})
}
​
/**
* 参数处理
* @param params 参数
*/
export function tansParams(params) {let result = ''for (const propName of Object.keys(params)) {const value = params[propName]var part = encodeURIComponent(propName) + "="if (value !== null && value !== "" && typeof (value) !== "undefined") {if (typeof value === 'object') {for (const key of Object.keys(value)) {if (value[key] !== null && value[key] !== "" && typeof (value[key]) !== 'undefined') {let params = propName + '[' + key + ']'var subPart = encodeURIComponent(params) + "="result += subPart + encodeURIComponent(value[key]) + "&"}}} else {result += part + encodeURIComponent(value) + "&"}}}return result
}

5.在utils.js工具文件下创建permission.js文件-导航守卫设置白名单,页面拦截器

import { getAccessToken } from '@/utils/auth'
​
// 登录页面
const loginPage = "/pages/login"
​
// 页面白名单
const whiteList = ['/pages/login', '/pages/common/webview/index'
]
​
// 检查地址白名单
function checkWhite(url) {const path = url.split('?')[0]return whiteList.indexOf(path) !== -1
}
​
// 页面跳转验证拦截器
let list = ["navigateTo", "redirectTo", "reLaunch", "switchTab"]
list.forEach(item => {uni.addInterceptor(item, {invoke(to) {if (getAccessToken()) {if (to.path === loginPage) {uni.reLaunch({ url: "/" })}return true} else {if (checkWhite(to.url)) {return true}uni.reLaunch({ url: loginPage })return false}},fail(err) {console.log(err)}})
})

6.在main.js中引入导航守卫文件

// permission
// 导航守卫文件
import './permission' 

7.发送请求例子

// 对接文档服务器封装
import upload from '@/utils/upload'
// 对接普通api接口
import request from '@/utils/request'
​
// 登录方法-不需要添加token-请求头添加isToken: false
export function login(username, password, captchaVerification) {const data = {username,password,captchaVerification}return request({url: '/system/auth/login',headers: {isToken: false},'method': 'POST','data': data})
}
​
// 查询用户个人信息-普通api添加token+用户id
export function getUserProfile() {return request({url: '/system/user/profile/get',method: 'GET'})
}
​
// 用户头像上传-对接文档服务器
export function uploadAvatar(data) {return upload({url: '/system/user/profile/update-avatar',method: 'PUT',name: data.name,filePath: data.filePath})
}

总结:

经过这一趟流程下来相信你也对 uni-app 使用uni.request封装发送api请求文档服务器请求导航守卫 有了初步的深刻印象,但在实际开发中我 们遇到的情况肯定是不一样的,所以我们要理解它的原理,万变不离其宗。加油,打工人!

什么不足的地方请大家指出谢谢 -- 風过无痕

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/9700.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Cisco IOS操作(红茶三杯CCNA)

Cisco路由器组件 CPU:执行指令 RAM:断电内容丢失 - 运行操作系统 - 运行配置文件 - IP路由表 - ARP缓存 - 数据包缓存区 ROM:保存开机自检软件,存储路由器的启动引导程序 - bootstrap指令 - 基本的自检软件 - 迷你版IOS 非易失RAM…

STM32CubeMX配置STM32G031多通道ADC + DMA采集(HAL库开发)

时钟配置HSI主频配置64M 勾选打开8个通道的ADC 使能连续转换模式 添加DMA DMA模式选择循环模式 使能DMA连续请求 采样时间配置160.5 转换次数为8 配置好8次转换的顺序 配置好串口,选择异步模式配置好需要的开发环境并获取代码 修改main.c 串口重定向 #include &…

从上到下打印二叉树

题目描述 从上到下打印出二叉树的每个节点,同一层的节点按照从左到右的顺序打印。 例如: 给定二叉树: [3,9,20,null,null,15,7], 返回: [3,9,20,15,7] 算法思想 建立一个vector数组ret用来当做返回的结果数组,建立一个队列用来接收二叉树…

ELK环境搭建——概况

Elastic Stack,核心产品包括 Elasticsearch、Kibana、Beats 和 Logstash等等。能够安全可靠地从任何来源获取任何格式的数据,然后对数据进行搜索、分析和可视化。 目录 一:Elasticsearch: 1.1 从数据中探寻各种问题的答案 1.1.1 定义您自己的搜索方式

毓恬冠佳冲刺上市:打破汽车天窗外商垄断,长安汽车为其主要客户

撰稿|行星 来源|贝多财经 7月23日,上海毓恬冠佳科技股份有限公司(以下简称“毓恬冠佳”)在深圳证券交易所的审核状态变更为“已问询”。据贝多财经了解,毓恬冠佳于2023年6月27日递交招股书,准备在创业板上市。 本次冲…

docker入门讲解

目录 第 1 章 Docker核心概念与安装 为什么使用容器? Docker是什么 Docker设计目标 Docker基本组成

pycharm中运行py文件时,报错:找不到自己编写的包等目录问题ModuleNotFoundError: No module named ‘xxx‘

【问题描述】:pycharm中运行py文件时,报错:找不到自己编写的包等目录问题 【报错】: ModuleNotFoundError: No module named ‘xxx’ ERROR: file not found 【问题定位】:运行的py文件和用到的包或者数据不在同一个文件目录下时…

基于Java+SpringBoot+vue前后端分离网上租赁系统设计实现

博主介绍:✌全网粉丝30W,csdn特邀作者、博客专家、CSDN新星计划导师、Java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ 🍅文末获取源码联系🍅 👇🏻 精彩专…

Langchain 的 Structured output parser

Langchain 的 Structured output parser 当您想要返回多个字段时,可以使用此输出解析器。虽然 Pydantic/JSON 解析器更强大,但我们最初尝试了仅具有文本字段的数据结构。 示例代码, from langchain.output_parsers import StructuredOutput…

如何使用GPT作为SQL查询引擎的自然语言

​生成的AI输出并不总是可靠的,但是下面我会讲述如何改进你的代码和查询的方法,以及防止发送敏感数据的方法。与大多数生成式AI一样,OpenAI的API的结果仍然不完美,这意味着我们不能完全信任它们。幸运的是,现在我们可以…

windows系统问题

删除服务 方法 1:使用「注册表」删除 Windows 服务 注册表是 Windows 操作系统和应用程序存储其低层级配置的数据库,当然也包括了「服务」。在 Windows 中删除任何「服务」最简单方法就是使用「注册表编辑器」: 使用Windows R快捷键打开「…

Vue前端渲染blob二进制对象图片的方法

近期做开发,联调接口。接口返回的是一张图片,是对二进制图片处理并渲染,特此记录一下。 本文章是转载文章,原文章:Vue前端处理blob二进制对象图片的方法 接口response是下图 显然,获取到的是一堆乱码&…

FUNBOX_1靶场详解

FUNBOX_1靶场复盘 这个系列的靶场给出的干扰因素都挺多的,必须从中找到有用的线索才可以。 这个靶场你扫描到ip地址后打开网页会发现,ip自动转换成域名了,所以我们需要添加一条hosts解析才可以。 192.168.102.190 funbox.fritz.box从目录…

element 表格里,每一行都循环使用el-popover组件,关闭按钮失效问题如何解决?

具体代码 <!DOCTYPE html> <html lang"zh"><head><meta charset"UTF-8"><title></title><link rel"stylesheet" href"https://unpkg.com/element-ui/lib/theme-chalk/index.css"><styl…

解决了项目中几个比较搞心态的bug(前端vue、小程序)

1、keep-alive 正常keep-alive的使用便可以做项目的缓存&#xff0c;但是我们的项目很不正常 项目是属于动态缓存&#xff0c;动态缓存有一个弊端 举个栗子&#xff1a; a组件为设置了需要缓存的页面&#xff1b; b组件为设置了需要缓存的页面&#xff1b; c组件为设置了不需…

资源成本降低70%!华为MetaERP资产核算的Serverless架构实践

资产核算是指在一定的财务周期&#xff0c;对企业拥有的房屋建筑物、机器设备、商标权和专利权等资产的取得、折旧和处置的会计核算&#xff0c;反映企业固定资产、无形资产的增减变动和价值分摊活动。华为资产核算产品&#xff0c;支撑企业资产从获取到处置全生命周期的管理和…

速锐得智能汽车车身域CANFD控制芯片MCU接口电路原理图

CAN总线技术不仅涉及汽车电子和轨道交通&#xff0c;还涉及医疗器械、工业控制、智能家居和机器人网络互连&#xff0c;这些行业对CAN产品的稳定性和抗干扰能力都有很高的要求。 上篇我们讲了在汽车CAN FD上&#xff0c;数据出错可能导致数据位被错误地解析为填充位&#xff0c…

MyBatis源码剖析之二级缓存细节

MyBatis是一个流行的Java持久化框架&#xff0c;它提供了许多功能&#xff0c;包括支持一级缓存和二级缓存。 一级缓存是默认开启的&#xff0c;它是在SqlSession层面的缓存。在同一个SqlSession中&#xff0c;如果执行了相同的SQL语句&#xff0c;那么第二次执行将从缓存中获取…

求整数中的最大值

才用打擂台的形式&#xff0c;先放一个数max在擂台上&#xff0c;然后每个数都上去和他比较&#xff0c;如果上去的那个数比max大&#xff0c;那么就把max替换成那个数站在擂台上&#xff0c;依次比较&#xff0c;直到所有数都比较完后&#xff0c;站在擂台上的那个max就是最大…

2023年深圳杯数学建模C题无人机协同避障航迹规划

2023年深圳杯数学建模 C题 无人机协同避障航迹规划 原题再现&#xff1a; 平面上A、B两个无人机站分别位于半径为500 m的障碍圆两边直径的延长线上&#xff0c;A站距离圆心1 km&#xff0c;B站距离圆心3.5 km。两架无人机分别从A、B两站同时出发&#xff0c;以恒定速率10 m/s…