JavaScript如何实现防止重复的网络请求的示例


Posted in Javascript onJanuary 28, 2021

前言

在开发中,经常会遇到接口重复请求导致的各种问题。
对于重复的网络请求,会导致页面更新多次,发生页面抖动的现象,影响用户体验。
例如当前页面请求还未响应完成,就切换到其他路由,那么这些请求直到响应返回才会中止。
无论从用户体验或者从业务严谨方面来说,取消无用的请求确实是需要避免的。

实现思路

JavaScript如何实现防止重复的网络请求的示例

**  1.在发送请求前先拦截当前请求地址 (url + 方法 + 参数);
**  2.开启一个请求队列用于保存 当前地址;
**  3.每次请求查看请求队列里面有没有当前url地址;
**  4.如果请求队列里有当前url地址就取消当前请求,
**  5.如果没有就发送请求,当请求数据返回后,请求队列里清除当前url地址。

1.平时我们写接口是这样的:

请求接口文件

import { http } from '@/plugin/axios'; // 导入请求接口 http

// 初始化
export function getInit(params) {
  return http({
    method: 'get',
    url: '/xxx/xxx/xx',
    params,
  });
}

主要就是这里执行 http方法的时候做操作;
执行http函数的时候能获取到请求所有配置 config ,返回promise对象。

2.这里演示使用axios,思路是执行请求函数的时候外面包一层

axios.js配置文件

import axios from 'axios';
import { httpRequest, completeRequest } from './options'; // 这里就是我们要实现的逻辑文件

// 里面做一些请求拦截,响应拦截操作 具体查看axios文档
const service = axios.create({
  baseURL: 'xxx/xxx',
});

// 请求拦截器
service.interceptors.request.use(config => {}, error => {})

// 响应拦截器
service.interceptors.response.use(response => {
 completeRequest(response); // 2.响应请求回来执行
}, error => {
 
})

export function http(config) { // => 这里config就是传递的请求配置参数
  return httpRequest(config, service); // + 1.在这里做一些逻辑操作
}

3.防止重复网络配置文件

options.js
(1)发送请求前,查看请求队列里是否有当前请求(url地址来判断)

  • 请求队列有当前url地址, 取消请求  返回promise.reject失败
  • 没有当前请求,正常发送请求;
/**
 * 职责: 防止重复的网络请求
 *
 */

let list = new Set(); // 1.请求队列

// 合并 方法 参数 url地址
function getUrl(config = {}) {
 // get请求 params参数 post请求 data参数, baseURL
 const { url, method, params, data, baseURL = '' } = config;
 const urlVal = url.replace(baseURL, '');
 return `${urlVal}?${method === 'get' ? getformatObjVal(params) : getformatObjVal(data)}`;
}

// 处理 url地址 
const getformatObjVal = (obj) => {
 obj = typeof obj === 'string' ? JSON.parse(`${obj}`) : obj;
 var str = [];
 for (let p in obj) {
  if (obj.hasOwnProperty(p) && p !== '_t') {
   var item = obj[p] === null ? '' : obj[p]; // 处理null
   str.push(encodeURIComponent(p) + '=' + encodeURIComponent(item));
  }
 }
 return str.join('&');
}

// 2.请求方法
export function httpRequest(config = {}, axios) {
 const url = getUrl(config); //3. 这里我们获取到了URL地址

 if (list.has(url)) { // 4.查看请求队列是否有当前url地址
  return Promise.reject('In the request'); // 5.在请求队列里面 取消当前请求, 返回Promise失败结果
 }
 
 // 6. 请求队列没有当前url地址 发送请求并把url地址存入请求队列里
 list.add(url);
 return Promise.resolve(axios); 
}

(2)请求响应回来后,在请求队列里删除当前url地址; (下一次请求就可以正常发送)
​ options.js

// 请求响应回来执行这个函数
export function completeRequest(response = {}) {
 const { config } = response; // 1.response里面config能拿到配置参数
 const url = getUrl(config); // 2.获取url地址 
 if (list.has(url)) {
  list.delete(url); // 3.删除请求队列中的当前请求url地址
 }
}

axios.js

import axios from 'axios';
import { httpRequest, completeRequest } from './options'; // 防止重复请求

const service = axios.create({
  baseURL: 'xxx/xxx',
});

// 请求拦截器
service.interceptors.request.use(config => {}, error => {})

// 响应拦截器
service.interceptors.response.use(response => {
 completeRequest(response); // 2.响应请求回来执行 +
}, error => {
 
})


// 导出请求
export function http(config) {
  return httpRequest(config, service); // 1.发送请求前执行
}

到这里已经实现了防止重复的网络请求,但还有一个问题,响应请求发生异常了要清除请求队列中当前url地址。不清理,下一次发送请求直接被取消掉 (这里我就随便写了一个方法,把请求队列全部清空,大家可以按自己场景来写)。

/**
 * 清空所有请求队列
 */
export function clearRequestList() {
 list = new Set(); // 这里我就直接清空了
}

完整http.js文件

import axios from 'axios';
import { httpRequest, completeRequest, clearRequestList } from './options'; // 防止重复请求 +

const service = axios.create({
  baseURL: 'xxx/xxx',
});

// 请求拦截器
service.interceptors.request.use(config => {}, error => {})

// 响应拦截器
service.interceptors.response.use(response => {
 completeRequest(response); // 2.响应请求回来执行
}, error => {
 clearRequestList(); // + 
})


// 导出请求
export function http(config) {
  return httpRequest(config, service); // 1.发送请求前执行
}

完整options.js

/**
 * 职责: 防止重复的网络请求
 *
 */

let list = new Set(); // 1.请求队列

// 合并 方法 参数 url地址
function getUrl(config = {}) {
 // get请求 params参数 post请求 data参数, baseURL
 const { url, method, params, baseURL = '' } = config;
 const urlVal = url.replace(baseURL, '');
 return `${urlVal}?${method === 'get' ? getformatObjVal(params) : 'post'}`;
}

// 处理 url地址 
const getformatObjVal = (obj) => {
 obj = typeof obj === 'string' ? JSON.parse(`${obj}`) : obj;
 var str = [];
 for (let p in obj) {
  if (obj.hasOwnProperty(p) && p !== '_t') {
   var item = obj[p] === null ? '' : obj[p]; // 处理null
   str.push(encodeURIComponent(p) + '=' + encodeURIComponent(item));
  }
 }
 return str.join('&');
}

// 2.请求方法
export function httpRequest(config = {}, axios) {
 const url = getUrl(config); //3. 这里我们获取到了URL地址

 if (list.has(url)) { // 4.查看请求队列是否有当前url地址
  return Promise.reject('In the request'); // 5.在请求队列里面 取消当前请求, 返回Promise失败结果
 }

 // 6. 请求队列没有当前url地址 发送请求并把url地址存入请求队列里
 list.add(url);
 return Promise.resolve(axios);
}


/**
 * 请求响应回来执行这个函数
 */
export function completeRequest(response = {}) {
 const { config } = response; // 1.response里面config能拿到配置参数
 const url = getUrl(config); // 2.获取url地址 
 list.has(url) && list.delete(url); // 3.删除请求队列中的当前请求url地址
}

/**
 * 清空所有请求队列
 */
export function clearRequestList(error) {
 // error 可以获取到配置, 做一些操作。
 list = new Set(); // 这里我就直接清空了
}

以上就是我实现防止网络请求的方式,之前我有使用过axios中CancelToken来进行取消请求;当会有一些问题。

  1. 需要配置请求文件,不友好,团队开发配置也比较麻烦。
  2. 需要给每个请求都配置CancelToken。  有两个方法使用它 具体可以参考官网文档

到此这篇关于JavaScript如何实现防止重复的网络请求的示例的文章就介绍到这了,更多相关JavaScript 防止重复的网络请求内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Javascript 相关文章推荐
User Scripts: Video Download by User Scripts
May 14 Javascript
javascript写的一个链表实现代码
Oct 25 Javascript
JavaScript中getUTCMinutes()方法的使用详解
Jun 10 Javascript
基于jQuery实现的菜单切换效果
Oct 16 Javascript
详解javascript事件冒泡
Jan 09 Javascript
AngularJS通过$sce输出html的方法
Sep 22 Javascript
jQuery插件echarts实现的多折线图效果示例【附demo源码下载】
Mar 04 Javascript
Node.js使用orm2进行update操作时关联字段无法修改的解决方法
Jun 13 Javascript
详解vuex commit保存数据技巧
Dec 25 Javascript
Angular如何由模板生成DOM树的方法
Dec 23 Javascript
使用JavaScript通过前端发送电子邮件
May 22 Javascript
Vue组件跨层级获取组件操作
Jul 27 Javascript
JavaScript实现跟随鼠标移动的盒子
Jan 28 #Javascript
vue.js实现点击图标放大离开时缩小的代码
Jan 27 #Vue.js
使用JS实现鼠标放上图片进行放大离开实现缩小功能
Jan 27 #Javascript
vscode自定义vue模板的实现
Jan 27 #Vue.js
vue+echarts实现中国地图流动效果(步骤详解)
Jan 27 #Vue.js
js实现鼠标切换图片(无定时器)
Jan 27 #Javascript
JavaScript实现切换多张图片
Jan 27 #Javascript
You might like
在PHP的图形函数中显示汉字
2006/10/09 PHP
论坛头像随机变换代码
2006/10/09 PHP
php文件上传后端处理小技巧
2016/05/22 PHP
原生php实现excel文件读写的方法分析
2018/04/25 PHP
THINKPHP-Apache服务器中使用Alias虚拟目录URL重写 隐藏index.php
2021/03/09 PHP
jQuery学习笔记之jQuery原型属性和方法
2014/06/09 Javascript
jQuery使用serialize()表单序列化时出现中文乱码问题的解决办法
2016/07/27 Javascript
jQuery实现单击按钮遮罩弹出对话框效果(1)
2017/02/20 Javascript
jq源码解析之绑在$,jQuery上面的方法(实例讲解)
2017/10/13 jQuery
使用3D引擎threeJS实现星空粒子移动效果
2020/09/13 Javascript
chorme 浏览器记住密码后input黄色背景处理方法(两种)
2017/11/22 Javascript
angular 实现同步验证器跨字段验证的方法
2019/04/11 Javascript
javascript网页随机点名实现过程解析
2019/10/15 Javascript
微信分享invalid signature签名错误踩过的坑
2020/04/11 Javascript
JS实现躲避粒子小游戏
2020/06/18 Javascript
Vue项目中使用mock.js的完整步骤
2021/01/12 Vue.js
[04:17]DOTA2完美盛典,rOtk、BurNIng携手巴图演唱《倔强》
2017/11/28 DOTA
python在windows和linux下获得本机本地ip地址方法小结
2015/03/20 Python
自己编程中遇到的Python错误和解决方法汇总整理
2015/06/03 Python
Python ValueError: invalid literal for int() with base 10 实用解决方法
2015/06/21 Python
django celery redis使用具体实践
2019/04/08 Python
在linux下实现 python 监控usb设备信号
2019/07/03 Python
python 实现在shell窗口中编写print不向屏幕输出
2020/02/19 Python
Keras Convolution1D与Convolution2D区别说明
2020/05/22 Python
Python列表推导式实现代码实例
2020/09/09 Python
python中pivot()函数基础知识点
2021/01/03 Python
美国伊甸园兄弟种子公司:Eden Brothers
2018/07/01 全球购物
Sisley法国希思黎中国官网:享誉全球的奢华植物美容品牌
2019/06/30 全球购物
Can a struct inherit from another class? (结构体能继承类吗)
2014/07/22 面试题
安全资料员岗位职责
2013/12/14 职场文书
爱情检讨书大全
2014/01/21 职场文书
幼儿园教师考核制度
2014/02/01 职场文书
企业委托书范本
2014/09/13 职场文书
正风肃纪剖析材料
2014/09/30 职场文书
酒会开场白大全
2015/06/01 职场文书
MySQL中dd::columns表结构转table过程及应用详解
2022/09/23 MySQL