当前位置: 首页 > news >正文

企业网站建设论文网站制作的流程是什么

企业网站建设论文,网站制作的流程是什么,注册完域名后如何做网站,德州市网站建设前言 关于axios全局loading的封装博主已经发过一次了,这次是在其基础上增加了token的无感刷新。 token无感刷新流程 首次登录的时候会获取到两个token(AccessToken,RefreshToken)持久化保存起来(localStorage方案&a…

前言

关于axios全局loading的封装博主已经发过一次了,这次是在其基础上增加了token的无感刷新。

token无感刷新流程

  • 首次登录的时候会获取到两个token(AccessToken,RefreshToken)
  • 持久化保存起来(localStorage方案)
  • 正常请求业务接口的时候携带AccessToken
  • 当接口口返回401权限错误时,使用RefreshToken请求接口获取新的AccessToken
  • 替换原有旧的AccessToken,并保存
  • 继续未完成的请求,携带AccessToken
  • RefreshToken也过期了,跳转回登录页面,重新登录

后端设计

这里采用node简单实现的后台接口服务

  • 后端存有两个字段,分别保存长短token,并且每一段时间更新他们
  • 短token过期,返回 returncode:104;长token过期,返回 returncode: 108;请求成功返回returncode: 0;
  • 请求头中pass用来接收客户端长token,请求头中authorization用来接收客户端短token

1、创建一个新文件夹,通过vscode打开,运行:

npm init -y 

2、安装koa

npm i koa -s 

3、安装nodemon

npm i nodemon -g 

4、使用路由中间件

npm i koa-router -S 

5、跨域处理

npm i koa2-cors 

6、新建routes/index.js

const router = require("koa-router")();
let accessToken = "init_s_token"; //短token
let refreshToken = "init_l_token"; //长token/* 5s刷新一次短token */
setInterval(() => {accessToken = "s_tk" + Math.random();
}, 5000);/* 一小时刷新一次长token */
setInterval(() => {refreshToken = "l_tk" + Math.random();
}, 600000);/* 登录接口获取长短token */
router.get("/login", async (ctx) => {ctx.body = {returncode: 0,accessToken,refreshToken,};
});/* 获取短token */
router.get("/refresh", async (ctx) => {//接收的请求头字段都是小写的let { pass } = ctx.headers;if (pass !== refreshToken) {ctx.body = {returncode: 108,info: "长token过期,重新登录",};} else {ctx.body = {returncode: 0,accessToken,};}
});/* 获取应用数据1 */
router.get("/getData", async (ctx) => {let { authorization } = ctx.headers;if (authorization !== accessToken) {ctx.body = {returncode: 104,info: "token过期",};} else {ctx.body = {code: 200,returncode: 0,data: { id: Math.random() },};}
});/* 获取应用数据2 */
router.get("/getData2", async (ctx) => {let { authorization } = ctx.headers;if (authorization !== accessToken) {ctx.body = {returncode: 104,info: "token过期",};} else {ctx.body = {code: 200,returncode: 0,data: { id: Math.random() },};}
});module.exports = router; 

7、创建index.js文件

const Koa = require('koa')
const app = new Koa();
const index = require('./routes/index')const cors = require('koa2-cors');app.use(cors());app.use(index.routes(),index.allowedMethods())app.listen(4000,() => {console.log('server is listening on port 4000')
}) 

8、`配置package.json

"dev":"nodemon index.js", 

9、运行 npm run dev,这时服务端已准备好

npm run dev

前端源码

interceptors.ts

/** axios封装* 请求拦截、相应拦截、错误统一处理*/
import Axios from "axios";
import { ElMessage, ElLoading } from "element-plus";
import _ from "lodash";
import router from "@/router";
import BaseRequest from "@/request/request";
const axios = Axios.create({//baseURL: localStorage.getItem("address")?.toString(), // url = base url + request url// timeout: 50000 // request timeout
});
// loading对象
let loadingInstance: { close: () => void } | null;
// 变量isRefreshing
let isRefreshing = false;
// 后续的请求队列
let requestList: ((newToken: any) => void)[] = [];
// 请求合并只出现一次loading
// 当前正在请求的数量
let loadingRequestCount = 0;
// post请求头
axios.defaults.headers.post["Content-Type"] = "application/json;charset=UTF-8";
// request interceptoraxios.interceptors.request.use((config: any) => {let loadingTarget = "body";if (config.headers.loadingTarget) {loadingTarget = config.headers.loadingTarget;}const isShowLoading = config.headers.isShowLoading;const target = document.querySelector(loadingTarget);if (target && !isShowLoading) {// 请求拦截进来调用显示loading效果showLoading(loadingTarget);}// do something before request is sent// if (sessionStorage.getItem("token")) {//   config.headers.Authorization =//     "Bearer " + sessionStorage.getItem("token"); // 让每个请求携带自定义 token 请根据实际情况自行修改// }if (config.url) {// 此处为 Refresh Token 专用接口,请求头使用 Refresh Tokenif (config.url.indexOf("/refresh") >= 0) {config.headers.Authorization = localStorage.getItem("RefreshToken");} else if (!(config.url.indexOf("/login") !== -1)) {// 其他接口,请求头使用 Access Tokenconfig.headers.Authorization = localStorage.getItem("accessToken");}}return config;},(error) => {// do something with request errorconsole.log(error); // for debugreturn Promise.reject(error);}
);
// http response 拦截器
axios.interceptors.response.use(async (response) => {setTimeout(() => {hideLoading();}, 200);const data = response.data;if (data.code == "401") {// 控制是否在刷新token的状态if (!isRefreshing) {// 修改isRefreshing状态isRefreshing = true;// 这里是获取新token的接口,方法在这里省略了。const url = `/refresh`;const BaseRequestFun = new BaseRequest(url, "");BaseRequestFun.get().then(async (res) => {if (res && res.accessToken) {console.log("a");// 新tokenconst newToken = res.accessToken;// 保存新的accessTokenlocalStorage.setItem("accessToken", newToken);// 替换新accessTokenresponse.config.headers.Authorization = newToken;// token 刷新后将数组里的请求队列方法重新执行requestList.forEach((cb) => cb(newToken));// 重新请求完清空requestList = [];// 继续未完成的请求const resp = await axios.request(response.config);// 重置状态isRefreshing = false;// 返回请求结果return resp;} else {// 清除tokenlocalStorage.clear();// 重置状态isRefreshing = false;// 跳转到登录页router.replace("/");}});} else {// 后面的请求走这里排队// 返回未执行 resolve 的 Promisereturn new Promise((resolve) => {// 用函数形式将 resolve 存入,等待获取新token后再执行requestList.push((newToken) => {response.config.headers.Authorization = newToken;resolve(axios(response.config));});});}}return data;},(err) => {setTimeout(() => {hideLoading();}, 200);// 返回状态码不为200时候的错误处理ElMessage({message: err.toString(),type: "error",duration: 5 * 1000,});return Promise.resolve(err);}
);
// 显示loading的函数 并且记录请求次数 ++
const showLoading = (target: any) => {if (loadingRequestCount === 0) {loadingInstance = ElLoading.service({lock: true,text: "加载中...",target: target,background: "rgba(255,255,255,0.5)",});}loadingRequestCount++;
};// 隐藏loading的函数,并且记录请求次数
const hideLoading = () => {if (loadingRequestCount <= 0) return;loadingRequestCount--;if (loadingRequestCount === 0) {toHideLoading();}
};// 防抖:将 300ms 间隔内的关闭 loading 便合并为一次. 防止连续请求时, loading闪烁的问题。
const toHideLoading = _.debounce(() => {// eslint-disable-next-line @typescript-eslint/ban-ts-comment// @ts-ignoreloadingInstance.close();loadingInstance = null;
}, 300);export default axios;

request.ts

import instance from "./interceptors";
import { ElMessage } from "element-plus";export default class baseRequest {private url: any;private params: any;constructor(url: any, params: any) {this.url = url;this.params = typeof params === "undefined" ? {} : params;}get(...params: any[]) {return instance.get(this.url, {params: this.params,headers: {loadingTarget: params[0],isShowLoading: params[1] === undefined ? true : params[1],},}).then((res: any) => {if (res.code === 200) {return Promise.resolve(res);} else {ElMessage({message: res.entitys[Object.keys(res.entitys)[0]],type: "error",duration: 5 * 1000,});return Promise.resolve(false);}}).catch((e) => {ElMessage({message: e,type: "error",duration: 5 * 1000,});Promise.resolve(false);});}post(...params: any[]) {return instance.post(this.url, this.params, {headers: {loadingTarget: params[0],isShowLoading: params[1] === undefined ? true : params[1],},}).then((res: any) => {if (res.code === "200") {return Promise.resolve(res.entitys);} else {ElMessage({message: res.entitys[Object.keys(res.entitys)[0]],type: "error",duration: 5 * 1000,});Promise.resolve(false);}}).catch((e) => {ElMessage({message: e,type: "error",duration: 5 * 1000,});Promise.resolve(false);});}put(...params: any[]) {return instance.put(this.url, this.params, {headers: {loadingTarget: params[0],isShowLoading: params[1] === undefined ? true : params[1],},}).then((res: any) => {if (res.code === "200") {return Promise.resolve(res.entitys);} else {ElMessage({message: res.entitys[Object.keys(res.entitys)[0]],type: "error",duration: 5 * 1000,});Promise.resolve(false);}}).catch((e) => {ElMessage({message: e,type: "error",duration: 5 * 1000,});Promise.resolve(false);});}delete(...params: any[]) {return instance.delete(this.url, {params: this.params,headers: {loadingTarget: params[0],isShowLoading: params[1] === undefined ? true : params[1],},}).then((res: any) => {if (res.code === "200") {return Promise.resolve(res.entitys);} else {ElMessage({message: res.entitys[Object.keys(res.entitys)[0]],type: "error",duration: 5 * 1000,});Promise.resolve(false);}}).catch((e) => {ElMessage({message: e,type: "error",duration: 5 * 1000,});Promise.resolve(false);});}upfile(...params: any[]) {return instance.post(this.url, this.params, {headers: {"Content-Type": "multipart/form-data","X-Requested-With": "XMLHttpRequest",loadingTarget: params[0],isShowLoading: params[1] === undefined ? true : params[1],},}).then((res: any) => {if (res.code === "200") {return Promise.resolve(res.entitys);} else {ElMessage({message: res.entitys[Object.keys(res.entitys)[0]],type: "error",duration: 5 * 1000,});Promise.resolve(false);}}).catch((e) => {ElMessage({message: e,type: "error",duration: 5 * 1000,});Promise.resolve(false);});}downfile(...params: any[]) {return instance.post(this.url, this.params, { responseType: "blob" }).then((res: any) => {const fileReader = new FileReader();fileReader.onload = function (e: any) {try {const jsonData = JSON.parse(e.target.result); // 说明是普通对象数据,后台转换失败if (jsonData.code) {ElMessage({message: jsonData.message,type: "error",duration: 5 * 1000,});Promise.resolve(false);}} catch (err) {// 解析成对象失败,说明是正常的文件流const url = window.URL.createObjectURL(res);const eleLink = document.createElement("a");eleLink.href = url;eleLink.download = params[2];// eleLink.download = "1.xls";document.body.appendChild(eleLink);eleLink.click();window.URL.revokeObjectURL(url);}};fileReader.readAsText(res);}).catch((e) => {ElMessage({message: e,type: "error",duration: 5 * 1000,});Promise.resolve(false);});}icd9Export() {return instance.post(this.url, this.params, { responseType: "blob" }).then((res: any) => {const fileReader = new FileReader();fileReader.onload = function (e: any) {try {const jsonData = JSON.parse(e.target.result); // 说明是普通对象数据,后台转换失败if (jsonData.code) {ElMessage({message: jsonData.message,type: "error",duration: 5 * 1000,});Promise.resolve(false);}} catch (err) {// 解析成对象失败,说明是正常的文件流const url = window.URL.createObjectURL(res);const eleLink = document.createElement("a");eleLink.href = url;eleLink.download = "icd9.xls";document.body.appendChild(eleLink);eleLink.click();window.URL.revokeObjectURL(url);}};fileReader.readAsText(res);}).catch((e) => {ElMessage({message: e,type: "error",duration: 5 * 1000,});Promise.resolve(false);});}icd10Export() {return instance.post(this.url, this.params, { responseType: "blob" }).then((res: any) => {const fileReader = new FileReader();fileReader.onload = function (e: any) {try {const jsonData = JSON.parse(e.target.result); // 说明是普通对象数据,后台转换失败if (jsonData.code) {ElMessage({message: jsonData.message,type: "error",duration: 5 * 1000,});Promise.resolve(false);}} catch (err) {// 解析成对象失败,说明是正常的文件流const url = window.URL.createObjectURL(res);const eleLink = document.createElement("a");eleLink.href = url;eleLink.download = "icd10.xls";document.body.appendChild(eleLink);eleLink.click();window.URL.revokeObjectURL(url);}};fileReader.readAsText(res);}).catch((e) => {ElMessage({message: e,type: "error",duration: 5 * 1000,});Promise.resolve(false);});}
}

测试vue

<template><div><el-button type="primary" @click="login()">登录</el-button><el-button type="primary" @click="getData()">接口一</el-button><el-button type="primary" @click="getData2()">接口二</el-button></div>
</template><script lang="ts" setup>
import BaseRequest from "@/request/request";
const login = () => {const url = `/login`;const BaseRequestFun = new BaseRequest(url, "");BaseRequestFun.get().then((res) => {if (res) {console.log();localStorage.setItem("accessToken", res.accessToken);localStorage.setItem("RefreshToken", res.refreshToken);}});
};
const getData = () => {const url = `/getData`;const BaseRequestFun = new BaseRequest(url, "");BaseRequestFun.get().then((res) => {if (res) {console.log(res);}});
};
const getData2 = () => {const url = `/getData2`;const BaseRequestFun = new BaseRequest(url, "");BaseRequestFun.get().then((res) => {if (res) {console.log(res);}});
};
</script><style lang="scss"></style>
http://www.hkea.cn/news/45069/

相关文章:

  • 淘宝做动效代码的网站seo的优化方向
  • 番禺建网站公司网站搜索工具
  • 安徽万振建设集团网站长春网站推广公司
  • 网站怎么制作 推广seo超级外链工具免费
  • 中小学网站建设探讨东莞seo整站优化火速
  • php是网站开发的语言吗企业网站的作用
  • 网站站外优化怎么做企业推广app
  • 拉趣网站是谁做的威海网站制作
  • 做宣传海报的网站百度导航2023年最新版
  • 湖南做网站 磐石网络windows优化大师官方免费
  • 制作网站的最新软件如何优化关键词的方法
  • 东莞工作招聘网最新招聘搜索 引擎优化
  • 宁波俄语网站建设免费发广告的平台有哪些
  • 郑州外贸网站建设及维护营销软件商城
  • 泉州百度关键词排名广州网站营销优化qq
  • 怎么做wep网站营销推广活动方案
  • 展示型网站php官方app下载安装
  • 嘉祥网站建设广东省自然资源厅
  • 忘记网站后台密码网站排名软件推荐
  • 怎么查公司网站有没有被收录火爆产品的推广文案
  • 绵阳网站建设 经开区网络教学平台
  • wordpress阅读量没改7个湖北seo网站推广策略
  • 网站建设成功案例方案找培训机构的平台
  • 园林绿化网站建设百度关键词优化公司
  • 个人如何建设网站网络营销方式有哪些分类
  • 北京做百度网站建设电商平台如何推广运营
  • 电脑个人网站怎么做网络销售新手入门
  • 海口网站建设 小黄网络手机百度搜索
  • 太原百度网站建设网站应该如何进行优化
  • 烟台市做网站uc浏览网页版进入