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 防止重复的网络请求内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • JS 实现请求调度器

    前言:JS 天然支持并行请求,但与此同时会带来一些问题,比如会造成目标服务器压力过大,所以本文引入"请求调度器"来节制并发度. TLDR; 直接跳转『抽象和复用』章节. 为了获取一批互不依赖的资源,通常从性能考虑可以用 Promise.all(arrayOfPromises)来并发执行.比如我们已有 100 个应用的 id,需求是聚合所有应用的 PV,我们通常会这么写: const ids = [1001, 1002, 1003, 1004, 1005]; const urlPrefi

  • jQuery+Ajax+js实现请求json格式数据并渲染到html页面操作示例

    本文实例讲述了jQuery+Ajax+js实现请求json格式数据并渲染到html页面操作.分享给大家供大家参考,具体如下: 1.先给json格式的数据: [ {"id":1,"name":"stan"}, {"id":2,"name":"jack"}, {"id":3,"name":"lucy"}, {"id&quo

  • 解决HttpPost+json请求---服务器中文乱码及其他问题

    好凌乱的题目,只是一些功能点的总结咯. 首先构造一个json对象用于存放数据,如果光加上header为utf-8就能解决中文就大错特错了... json对象可以put变量,也可以put对象.取的时候 obj.getJSONObject("people").getString("name") HttpClient httpClient = new DefaultHttpClient(); String url = "***"; HttpPost h

  • JavaScript实现串行请求的示例代码

    使用async和await var fn = async function(promiseArr) { for(let i = 0,len = arr.length; i<len; i++) { currentPromise = (promiseArr[i] instanceOf Promise) ? promiseArr[i] : Promise.resolve(promiseArr[i]); var result = await currentPromise; console.log(res

  • nodejs使用socket5进行代理请求的实现

    需要用到2个库, request socks5-http-client/lib/Agent/ 或 socks5-https-client/lib/Agent 因为一些已知原因,有时候,http.request请求无法拿到数据, 首先想到的是proxy,其次是socket5. 有了以上两个库,接下来的代码超级简单. const request = require('request'); var httpAgent = require('socks5-http-client/lib/Agent');

  • Spring中使用JSR303请求约束判空的实现

    1. 适用场景 有时候我们在表单里提交一系列参数, 到后台封装成一个对象, 要对对象的属性做各种字段值的约束; 这时候, 当然可以if-else一个一个的判断, 有更简洁的做法, 就是使用 JSR303+spring的validation: 2. 使用方法步骤(分3步) 实体类加字段约束注解 Controller类中@Valid标注启用(@Validated也兼容@Valid) BindingResult获取报错信息 2.1 实体类加字段约束注解 如我们要收集前端表单的字段数据到Person实体

  • PHP实现chrome表单请求数据转换为接口使用的json数据

    为什么要写转换程序 最近在做旧版程序迁移,旧的架构为常规的MVC模式,新版架构全部改成restful架构. 由于改版数据是一致的,但是请求结构不一致,新版的请求全部以json形式提交,为了方便测试,之前一直都是直接在浏览器打开开发者工具,然后把请求内容复制过来,然后手动改成json形式,由于之前数据量比较少,暂时未发现测试时候不方便的情况,但是今天遇到了数据比较多的情况,于是我想,为啥不写一段转换程序呢? 本身来说,程序的初衷应该是提高工作效率,这也是我之前缺少反思的地方,因此写下这篇文章做个记

  • PHP使用Http Post请求发送Json对象数据代码解析

    因项目的需要,PHP调用第三方 Java/.Net 写好的 Restful Api,其中有些接口,需要 在发送 POST 请求时,传入对象. Http中传输对象,最好的表现形式莫过于JSON字符串了,但是作为参数的接收方,又是需要被告知传过来的是JSON! 其实这不难,只需要发送一个 http Content-Type头信息即可,即 "Content-Type: application/json; charset=utf-8",参考代码如下: <?php /** * PHP发送J

  • Javascript原生ajax请求代码实例

    这篇文章主要介绍了Javascript原生ajax请求代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 代码如下 class Ajax{ constructor(url, method, data, callback_suc, callback_err, callback_run){ this.RT = true;//默认为异步请求 this.url = url; this.method = method || "POST";

  • JavaScript/TypeScript 实现并发请求控制的示例代码

    场景 假设有 10 个请求,但是最大的并发数目是 5 个,并且要求拿到请求结果,这样就是一个简单的并发请求控制 模拟 利用 setTimeout 实行简单模仿一个请求 let startTime = Date.now(); const timeout = (timeout: number, ret: number) => { return (idx?: any) => new Promise((resolve) => { setTimeout(() => { const compa

  • 在vue中使用jsonp进行跨域请求接口操作

    前言: 这里我们使用的是第三方插件jsonp. github网址:https://github.com/webmodules/jsonp 1.安装 npm install jsonp -S 2.引入 一般新建一个js文件来引入原始jsonp插件,然后对原始插件进行封装,对跨域接口参数的拼接,封装好这个jsonp文件后export出去,之后在哪里用到就再在那里import. 1.新建jsonp.js文件来封装原始jsonp插件 // 引入原始jsonp插件 import originJsonp f

  • 原生js实现ajax请求和JSONP跨域请求操作示例

    本文实例讲述了原生js实现ajax请求和JSONP跨域请求.分享给大家供大家参考,具体如下: 直接上代码: const ajax = (params = {}) => { const nowJson = params.jsonp ? jsonp(params) : json(params); function jsonp(params){ //创建script标签并加入到页面中 var callbackName = params.jsonp; var head = document.getEle

随机推荐