前端请求后台接口失败处理逻辑

news2025/1/12 3:47:13

前后分离项目,前端为uni-app(vue2),后台为java

后台api设置存在问题,部分公共接口为开放非登录用户访问权限

导致前台打开首页后立即跳转到登录提示页

怀疑是开了uni-app开发代理服务器,导致访问的代理服务器地址被拦截:

http://localhost:3030/api/bms/getPostPageList?page=1&limit=12&hot=1

由于不能通过单步执行,查找执行过程,只能在拦截代码中盲猜,始终未找到匹配的代码过程:

import Vue from 'vue'
import App from './App'
import store from './store'
import * as Db from './common/db.js'
import $AppEntryController from './AppEntryController.js'
import * as $apis from './apis/index.js'
import $mRouter from './common/router.js'
import $mUtils from './common/utils.js'
import $mConfig from "./config/index.config.js"
import $mAssetsPath from './config/assets.config.js'
import $mRoutesConfig from './config/routes.config.js'
import $mConstDataConfig from './config/constData.config.js'
import $modalHelper from './common/modalHelper.js'
import mPageView from "./components/m-page-view/m-page-view.vue"

Vue.component("yzb-page", mPageView)

const prePage = ()=>{
	let pages = getCurrentPages();
	let prePage = pages[pages.length - 2];
    // #ifdef H5
    return prePage;
    // #endif
	return prePage.$vm;
}
Vue.prototype.$mPage ={prePage};

Vue.config.productionTip = false;

Vue.prototype.$AppEntryController = $AppEntryController;

Vue.prototype.$store =store;

Vue.prototype.$apis = $apis;

Vue.prototype.$mRouter = $mRouter;

Vue.prototype.$mUtils = $mUtils;

Vue.prototype.$mConfig = $mConfig;

Vue.prototype.$mAssetsPath = $mAssetsPath;

Vue.prototype.$mRoutesConfig = $mRoutesConfig;

Vue.prototype.$mConstDataConfig = $mConstDataConfig;

Vue.prototype.$modalHelper = $modalHelper;

Vue.prototype.$db = Db;

import GoEasy from "./lib/goeasy-2.4.7.min.js";
const goEasy = GoEasy.getInstance({
	host:"hangzhou.goeasy.io",//应用所在的区域地址: 【hangzhou.goeasy.io |singapore.goeasy.io】
	appkey:"BC-88a9b720d97c4de88eefd2d64daf3fd0",	// common key,
    modules:["im"],
	// true表示支持通知栏提醒,false则表示不需要通知栏提醒
    allowNotification:true //仅有效于app,小程序和H5将会被自动忽略
});
Vue.prototype.GoEasy = GoEasy;
Vue.prototype.goEasy = goEasy;

$mRouter.beforeEach((navType, to) => {
	if (to.route === undefined) throw ("路由钩子函数中没有找到to.route对象,路由信息:" + JSON.stringify(to));

	console.log("进入路由过滤器")
	console.log("to=",to)
	if (to.route.path === $mRoutesConfig.login.path && store.getters.hasLogin) {
		uni.redirectTo({
			url: $mUtils.objParseUrlAndParam($mRoutesConfig.main.path, to.query)
		})
		return;
	}

	// 过滤需要权限的页面
	if (to.route.requiresAuth) {

		if (store.getters.hasLogin) {
			// 已经登录
			uni[navType]({
				url: $mUtils.objParseUrlAndParam(to.route.path, to.query)
			})
		} else {
			// 登录成功后的重定向地址和参数
			let query = {
				redirectUrl: to.route.path,
				...to.query
			}
			// 没有登录 是否强制登录?
			if (store.state.forcedLogin) {
				
				//#ifdef H5
				uni.redirectTo({
					url: $mUtils.objParseUrlAndParam($mRoutesConfig.loginPwd.path, query)
				})
				// #endif
				
				
				//#ifdef MP-WEIXIN
				uni.redirectTo({
					url: $mUtils.objParseUrlAndParam($mRoutesConfig.login.path, query)
				})
				// #endif

			} else {
				
				//#ifdef H5
				uni.redirectTo({
					url: $mUtils.objParseUrlAndParam($mRoutesConfig.loginPwd.path, query)
				})
				// #endif
				
				//#ifdef MP-WEIXIN
				uni.redirectTo({
					url: $mUtils.objParseUrlAndParam($mRoutesConfig.login.path, query)
				})
				// #endif

			}
		}
	} else {
		uni[navType]({
			url: $mUtils.objParseUrlAndParam(to.route.path, to.query)
		})
	}
})

App.mpType = 'app'

const app = new Vue({
	store,
	...App
})
app.$mount()


Vue.prototype.formatDate = function (t) {
    t = t || Date.now();
    let time = new Date(t);
    let str = time.getMonth() < 9 ? ('0' + (time.getMonth() + 1)) : (time.getMonth() + 1);
    str += '-';
    str += time.getDate() < 10 ? ('0' + time.getDate()) : time.getDate();
    str += ' ';
    str += time.getHours();
    str += ':';
    str += time.getMinutes() < 10 ? ('0' + time.getMinutes()) : time.getMinutes();
    return str;
}

// 控制全局日志开关
// console.log = (function (oriLogFunc) {
//   return function () {
//     //判断配置文件是否开启日志调试
//     if (!true) {
//       try{
//         oriLogFunc.call(console, ...arguments);
//       }catch(e){
//         console.error('console.log error', e);
//       }
//     }
//   }
// })(console.log);

重新查看uni-app发送http请求的代码段,发现在后台返回401时,代码直接跳转到登录流程:

import store from "@/store"
function HTTP(obj, config) {

	let defaultConfig = {
		isRes: false,
		loading: false
	}

	config = { ...defaultConfig,
		...config
	}


	// 如果需要显示loading,mask防止点击穿透
	config.loading && uni.showLoading({
		title: '加载中',
		mask: true
	});

	return new Promise((resolve, reject) => {

		let options = {
			url: "",
			method: "GET",
			data: {},
			dataType: "json",
			header: {
				"content-type": "application/json",
				"X-requested-With": "XMLHttpRequest",
				// 模拟用户登录
				//"X-Access-Token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE2OTQ1MjM5NDEsInVzZXJuYW1lIjoiYWRtaW4ifQ.iGxw-j0uNi-rY96KuP9B4Jgx-t-Uk2mYZxVWMb7ySbo"
			},
			success: (res) => {
				//console.log("HTTP请求结果:",res)
				//console.log("resolve:",resolve)
				uni.hideLoading();
				// 状态码为200
				if (res.statusCode == 200) {
					let data = res.data;

					//自动校验用户是否登录过期
					if (data.code == "01") {
						store.dispatch("reLogin");
						return;
					}

					//返回 { code:10000,msg:"消息",data:[] }
					if (config.isRes) {
						resolve(data)
					}
					// 返回 data:[]
					else {
						if (data.code == "200") {
							//console.log("data对象:",data)
							resolve(data.result||true)
						} else {
							wx.showToast({
								title: data.message,
								icon: "none",
								duration: 2000
							})
							reject(data.message);
						}
					}
				}else if(res.statusCode == 401) {
					store.dispatch("reLogin");
					return;
				} else {
					reject("HTTP:状态码异常!");
				}
			},
			fail: (err) => {
				uni.hideLoading();
				uni.showToast({
					title: "网络异常,请稍后再试!",
					icon: "none",
				})
				reject("网络异常,请稍后再试!");
			},
			complete: () => {}
		}

		options = { ...options,
			...obj
		};
		
		const OPENID = uni.getStorageSync("openId");
		const Token=uni.getStorageSync("token");
		// const location=uni.getStorageSync("location");
		// if(location){
		// 	//所有接口带上当前位置信息
		// 	options["data"]["latitude"] = location.latitude;
		// 	options["data"]["longitude"] = location.longitude;
		// 	options["data"]["pcitycode"] = location.pcitycode;
		// }
		console.log("Token==="+Token);
		if (OPENID) options["header"]["openId"] = OPENID;
		if (Token) options["header"]["X-Access-Token"] = Token;
		if (options.url && options.method) {
			wx.request(options);
		} else {
			wx.showToast({
				title: 'HTTP:缺失参数',
				icon: "none",
				duration: 2000
			})
		}
	})

}



export default {
	GET(url, data = {}, config) {
		return HTTP({
			url,
			data,
			method: "GET"
		}, config);
	},
	POST(url, data = {}, config) {
		return HTTP({
			url,
			data,
			method: "POST"
		}, config);
	},

	POSTformdata(url, data = {}, config) {
		return HTTP({
			url,
			data,
			method: "POST"
		}, config);
	}
}

这个过程对用户不友好,应提示用户未登录无法查看数据,让用户确认跳转还是留在原始位置。

解决办法是,使用wx.showModal(显示选择的对话框-带按钮),添加如下代码:

else if(res.statusCode == 401) {
		let res_message = res.data.message // 因为wx.showModal也有res,需要另存变量名
					wx.showModal({
					  title: '是否需要登录?',
					  content: '提示:'+res_message,
					  complete: (res) => {
						if (res.cancel) {
							reject(res_message);
						}
						if (res.confirm) {
							store.dispatch("reLogin");
						}
					  }
					})
					
					
					// 这不是正常的promise流程,添加这段代码的人不是原作者
					// store.dispatch("reLogin");
					// return;
				}

为了适应h5页面或小程序,添加条件编译:

效果:

 点确定则跳转到登录页面,点取消则留在当前页面。

参考:

https://www.cnblogs.com/guanxinjing/p/17337941.html

跨端兼容 | uni-app官网

注意uni-app条件编译不需要在配置文件设置条件未MP-WEIXIN或者H5,在编译时自动判断。

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

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

相关文章

openGaussDatakit让运维如丝般顺滑!

&#x1f4e2;&#x1f4e2;&#x1f4e2;&#x1f4e3;&#x1f4e3;&#x1f4e3; 哈喽&#xff01;大家好&#xff0c;我是【IT邦德】&#xff0c;江湖人称jeames007&#xff0c;10余年DBA及大数据工作经验 一位上进心十足的【大数据领域博主】&#xff01;&#x1f61c;&am…

全国三维数字化创新设计大赛湖北赛区省赛成功举办

须弥芥子&#xff0c;数字如海。10月14日—15日&#xff0c;2023 年数字科技文化节——第16届全国三维数字化创新设计大赛湖北赛区省赛暨产教联合体大会在武汉软件工程职业学院成功举行。 &#xff08;大赛全体专家领导合影&#xff09; 全国三维数字化创新设计大赛组委会副秘…

《论文阅读》LORA:大型语言模型的低秩自适应 2021

《论文阅读》LORA: LOW-RANK ADAPTATION OF LARGE LAN-GUAGE MODELS 前言简介现有方法模型架构优点前言 今天为大家带来的是《LORA: LOW-RANK ADAPTATION OF LARGE LAN-GUAGE MODELS》 出版: 时间:2021年10月16日 类型:大语言模型的微调方法 关键词: 作者:Edward Hu,…

大型电商系统的订单设计

前言&#xff1a;电商系统需要满足商品、订单、支付、会员、优惠券、秒杀、拼团、砍价、分销、积分等多种经营需求。其中订单模块是比较核心复杂的&#xff0c;需要架构师在上面下不少功夫。 0、电商系统业务架构图 电商系统&#xff0c;一般包括前台商城系统及后台管理系统&am…

《动手学深度学习 Pytorch版》 10.2 注意力汇聚:Nadaraya-Watson 核回归

import torch from torch import nn from d2l import torch as d2l1964 年提出的 Nadaraya-Watson 核回归模型是一个简单但完整的例子&#xff0c;可以用于演示具有注意力机制的机器学习。 10.2.1 生成数据集 根据下面的非线性函数生成一个人工数据集&#xff0c;其中噪声项 …

GoLong的学习之路(七)语法之slice(切片)

书接上回&#xff0c;上回书中写道&#xff1a;指针&#xff0c;并说明了基本引用类型分配内存new和特定情况下slice&#xff08;切片&#xff09;&#xff0c;map&#xff0c;channel等集合函数的内存分配make。这篇文章就开始说明&#xff0c;slice。 文章目录 slice&#xf…

人生道路选择,恳请前辈指点,半路出家学习java?

人生道路选择&#xff0c;恳请前辈指点&#xff0c;半路出家学习java&#xff1f; 首先答案肯定是可以的。Java作为一门高级语言&#xff0c;它很优秀地屏蔽了许多繁枝末节。很多科班出身的人上来可能会先学C、C&#xff0c;要学会怎么管理内存等很底层的事情&#xff0c;而在开…

联想拯救者Y7000笔记本WiFi频繁掉线的坑

2023年10月的某一天开始&#xff0c;跟了我近4年的联想拯救者Y7000本本&#xff0c;无线网总是频繁的掉线&#xff0c;连上没几分钟就断开了&#xff0c;同办公室的其他电脑没这种情况出现&#xff0c;一开始以为是运营商网络问题&#xff0c;或者路由器问题导致的&#xff0c;…

多通道图片的卷积过程

多通道&#xff08;channels&#xff09;图片的卷积 如果输入图片是三维的&#xff08;三个channel&#xff09;&#xff0c;例如&#xff08;8&#xff0c;8&#xff0c;3&#xff09;&#xff0c;那么每一个filter的维度就是&#xff08;3&#xff0c;3&#xff0c;3&#x…

一文彻底理解C语言中的指针

假定给你一块非常小的内存&#xff0c;这块内存只有8字节&#xff0c;这里也没有高级语言&#xff0c;没有操作系统&#xff0c;你操作的数据单位是单个字节&#xff0c;你该怎样读写这块内存呢&#xff1f; 注意这里的限定&#xff0c;再读一遍&#xff0c;没有高级语言&#…

rabbitmq-3.8.15集群、集群镜像模式安装部署

目录 一、环境 1、映射、域名、三墙 2、Erlang和socat安装&#xff08;三台服务器都实行&#xff09; 二、部署三台rabbitmq-3.8.15实例 1、rabbitmq官网下载地址 &#xff1a; 2、解压rabbitmq 3、添加系统变量 4、启动web插件、启动rabbitmq 5、在rabbitmq1上添加用…

(PyTorch)PyTorch中的常见运算(*、@、Mul、Matmul)

1. 矩阵与标量 矩阵&#xff08;张量&#xff09;每一个元素与标量进行操作。 import torch a torch.tensor([1,2]) print(a1) >>> tensor([2, 3]) 2. 哈达玛积&#xff08;Mul&#xff09; 两个相同尺寸的张量相乘&#xff0c;然后对应元素的相乘就是这个哈达玛…

常见的芯片封装技术

两边出pin的封装 1、DIP封装 DIP封装&#xff08;Dual In-line Package&#xff09;&#xff0c;也叫双列直插式封装技术&#xff0c;指采用双列直插形式封装的集成电路芯片&#xff0c;绝大多数中小规模集成电路均采用这种封装形式&#xff0c;其引脚数一般不超过100。DIP封装…

windows11录屏功能详解,记录你的精彩时刻

windows 11是微软最新推出的操作系统版本&#xff0c;拥有很多简单便捷的功能&#xff0c;包括内置的录屏工具&#xff0c;让用户可以轻松地录制屏幕内容。但是很多人不了解windows11录屏功能&#xff0c;本文将详细介绍windows 11录屏的三个方法&#xff0c;以及它们的优势和适…

HTTP图解基础知识

书&#xff1a;图解HTTP&#xff1b;分享书中学到的东西&#xff0c;内容很多&#xff0c;极具可玩性关键字&#xff1a;http&#xff0c;cookie&#xff0c;状态&#xff0c;头部字段&#xff0c;缓存&#xff0c;Etag 参考示例&#xff1a;https://zhuanlan.zhihu.com/p/…

ChatGPT在机器学习中的应用与实践

&#x1f482; 个人网站:【工具大全】【游戏大全】【神级源码资源网】&#x1f91f; 前端学习课程&#xff1a;&#x1f449;【28个案例趣学前端】【400个JS面试题】&#x1f485; 寻找学习交流、摸鱼划水的小伙伴&#xff0c;请点击【摸鱼学习交流群】 引言 随着人工智能技术…

【Gan教程 】 什么是变分自动编码器VAE?

名词解释&#xff1a;Variational Autoencoder&#xff08;VAE&#xff09; 一、说明 为什么深度学习研究人员和概率机器学习人员在讨论变分自动编码器时会感到困惑&#xff1f;什么是变分自动编码器&#xff1f;为什么围绕这个术语存在不合理的混淆&#xff1f;本文从两个角度…

docker搭建waline评论系统

我这里是给博客网站嵌入评论系统的 1.登录LeanCloud 国际版&#xff0c;没有账号可以注册个 链接&#xff1a;点击跳转 2.新建应用&#xff0c;选择开发版&#xff08;免费&#xff09;&#xff0c;商用版每个月最低消费5美刀。 3.在设置-应用凭证里面将AppID、AppKey、Maste…

基于springboot+vue校园短期闲置资源置换平台051

大家好✌&#xff01;我是CZ淡陌。一名专注以理论为基础实战为主的技术博主&#xff0c;将再这里为大家分享优质的实战项目&#xff0c;本人在Java毕业设计领域有多年的经验&#xff0c;陆续会更新更多优质的Java实战项目&#xff0c;希望你能有所收获&#xff0c;少走一些弯路…

YoloV8改进策略:独家原创,LSKA(大可分离核注意力)改进YoloV8,比Transformer更有效,包括论文翻译和实验结果

文章目录 摘要论文:《LSKA(大可分离核注意力):重新思考CNN大核注意力设计》1、简介2、相关工作3、方法4、实验5、消融研究6、与最先进方法的比较7、ViTs和CNNs的鲁棒性评估基准比较8、结论YoloV8官方结果改进一:测试结果摘要 本文给大家带来一种超大核注意力机制的改进方…