前端请求队列,解决多个请求同时请求一个接口导致阻塞的问题

这篇具有很好参考价值的文章主要介绍了前端请求队列,解决多个请求同时请求一个接口导致阻塞的问题。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1、背景

最近开发的数据大屏项目,使用echarts图表,通过拖拽的方式完成大屏的布局。
每一个图表编写一个vue文件,例如柱状图(barChart.vue):

<template>
  <div>
    <v-chart ref="barchart" :option="options" autoresize />
  </div>
</template>

<script>
export default {
  components: {},
  props: {
    value: Object,
    index: Number
  },
  data() {
    return {
      options: {
        grid: {},
        legend: {
          textStyle: {
            color: "#fff"
          }
        },
        xAxis: {
          type: "category",
          data: [],
          axisLabel: {
            show: true,
            textStyle: {
              color: "#fff"
            }
          }
        },
        yAxis: {
          type: "value",
          data: [],
          axisLabel: {
            show: true,
            textStyle: {
              color: "#fff"
            }
          }
        },
        series: [
          {
            data: [],
            type: "bar",
            barGap: "0%",
            itemStyle: {
              borderRadius: null
            }
          }
        ]
      },
      optionsStyle: {}, // 样式
      optionsData: {}, // 数据
      optionsSetup: {},
    };
  },
  mounted() {
    this.editorOptions();
  },
  methods: {
    // 修改图标options属性
    editorOptions() {
      this.setOptionsData();
    },
    // 数据解析
    setOptionsData() {
      const data = this.queryEchartsData(val);
      data.then(res => {
        this.renderingFn(optionsSetup, res);
      });
    },
  }
};
</script>

queryEchartsData的方法体如下:

queryEchartsData(params,_this) {
   return new Promise(async (resolve) => {
     const {code, data} = getData(params);
     if (code != 200) return
     resolve(data)
   })
 }

折线图等其他图表同理,都是使用queryEchartsData来获取后端接口返回的数据,queryEchartsData写在queryData.js中,然后通过全局混入的方式使用。当我一个大屏拖拽了太多的组件时,渲染时,每一个组件都同时通过queryEchartsData来获取数据,就会导致阻塞,最后一个接口返回数据的时间甚至可能达到9秒左右
vue 请求队列,前端,vue.js,javascriptvue 请求队列,前端,vue.js,javascript
vue 请求队列,前端,vue.js,javascript
从图上就可以看到光阻塞时长就达到了6秒,我的天啊!!!

2、思路

我实在受不了这种情况,于是就想办法解决喽,首先要弄清楚阻塞的原因到底在后端还是在前端。

  1. 后端使用ehcache来缓存接口数据
if (cacheHelper.exist(key)) {
    data = cacheHelper.stringGet(key);
} else {
	data = reportService.getChartData(dto)
	cacheHelper.stringSetExpire(datakey, JSON.toJSONString(data), 3600);
}

这样写完以后发现情况并没有任何变化,所以阻塞的情况是前端同时一次性发起太多请求导致的。

  1. 前端使用vuex来缓存接口数据
    在Vuex的store中定义一个状态,用于存储请求返回的数据。
// store.js
import Vue from 'vue';
import Vuex from 'vuex';

Vue.use(Vuex);

export default new Vuex.Store({
  state: {
    echartsData: {},
  },
  mutations: {
    setEchartsData(state, data) {
      state.echartsData[data.key] = data.data;
    },
  },
});

然后在执行queryEchartsData的时候,先判断store中是否已存在,如果存在就直接从store获取,否则就调用接口然后往store中写入。

但是在实际测试过程中,发现每一个vue文件进入到queryEchartsData后,在执行到getData的时候就不在往下走,而是跳转到下一个vue文件进入queryEchartsData方法,当所有vue文件都进入过queryEchartsData方法后,才会再继续执行getData后面的内容,无语,这个也行不通啊…

3、解决

总归是要解决,最后通过不停的喂ChatGPT,终于是找到了解决办法,使用请求队列和限流,实现一个请求队列,控制并发请求的数量,避免同时发起过多的请求。可以设置最大并发数,并根据需求进行请求的限流,以平衡请求和服务器资源之间的关系。代码如下:

// your-queue-file.js

/**
 * 创建请求队列
 * @param {number} maxConcurrentRequests 最大并发请求数量
 * @returns {object} 请求队列对象
 */
export function createRequestQueue(maxConcurrentRequests) {
  const queue = []; // 存储请求的队列
  let runningCount = 0; // 当前正在运行的请求数量

  /**
   * 处理下一个请求
   */
  async function processNextRequest() {
    if (runningCount >= maxConcurrentRequests || queue.length === 0) return;

    runningCount++;
    const request = queue.shift(); // 获取队列中的下一个请求

    try {
      const result = await request(); // 执行请求
      // 处理请求结果
      // ...
    } catch (error) {
      // 处理请求错误
      // ...
    } finally {
      runningCount--;
      processNextRequest(); // 处理下一个请求
    }
  }

  return {
    /**
     * 添加请求到队列
     * @param {function} request 请求函数,返回 Promise
     * @returns {Promise} 请求的 Promise 对象
     */
    add(request) {
      return new Promise((resolve, reject) => {
        queue.push(async () => {
          try {
            const result = await request(); // 执行请求
            resolve(result); // 请求成功,返回结果
          } catch (error) {
            reject(error); // 请求失败,返回错误信息
          }
        });

        processNextRequest(); // 添加请求后,处理下一个请求
      });
    }
  };
}
// 在 queryform.js 中
queryEchartsData(params, _this) {
  return new Promise(async (resolve) => {
    const result = await addToRequestQueue(() => getData(params));
    const { code, data } = result;
    if (code !== 200) return;
    resolve(data );
  });
}

// 在 main.js 中
import { createRequestQueue } from './your-queue-file'; // 导入请求队列的实现

const requestQueue = createRequestQueue(3); // 创建最大并发请求数为3的请求队列

Vue.mixin({
  methods: {
    addToRequestQueue(request) {
      return requestQueue.add(request);
    }
  }
});

测试结果如下:
vue 请求队列,前端,vue.js,javascript
除了最后一个接口时间在1.84秒,其他的都基本上在400多毫秒,而阻塞时间也控制在0.16ms左右
vue 请求队列,前端,vue.js,javascript
至此也算是解决了一桩心病啊,后面就可以在继续优化下去了!文章来源地址https://www.toymoban.com/news/detail-809326.html

到了这里,关于前端请求队列,解决多个请求同时请求一个接口导致阻塞的问题的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 接口响应时间长,前端返回请求超时解决

    1. 全局设置 axios.defaults.timeout = 时间 // 单位为毫秒 或 2. 封装的http请求 或 3. nginx默认的响应时间是60S 还需要修改nginx.conf文件 在配置的请求代理下添加 单位为秒

    2024年02月12日
    浏览(69)
  • 前端api接口请求错误问题解决方法

    最近我在群里看到很多同学在跟着视频写项目的时候,经常遇到一些关于资源请求API接口出现错误的问题,并在群里咨询。在这里,我想给大家分享一些解决这个问题的思路。 首先,我们需要对错误进行排查。这需要大家对HTTP请求有一定的了解。我在这里简单介绍一下,如

    2024年01月22日
    浏览(47)
  • 如何用java实现同时进行多个请求,可以将它们并行执行,从而减少总共的请求时间。

    1.使用线程池 通过使用Java提供的线程池,可以将多个请求分配到不同的线程中并行执行。可以通过创建固定数量的线程池,然后将请求分配给线程池来实现。线程池会自动管理线程的数量和复用,从而减少了线程创建和销毁的开销,提高了程序的性能。 以下是使用线程池实

    2024年02月12日
    浏览(58)
  • 前端异步请求并解决跨域问题(Ajax+axios框架)、后端响应多个数据(JSON)

    目录 一、前后端同步异步请求 1.同步请求: 2.异步请求: 3.跨域问题(前端问题) 4.axios框架(封装后) 二、后端向前端响应多个数据-JSON 1.同步请求:         发送一个请求,回应请求,回应的内容会覆盖浏览器中的内容,这样会 打断 前端其他的正常操作。 2.异步请求:

    2024年02月07日
    浏览(71)
  • linux文件锁(保证只能同时启动一个实例,不同时启动多个实例)

    可以使用Linux中的进程锁来实现只能启动一个实例的功能。一种常见的方法是使用文件锁(File Locking)。 可以在程序启动时创建一个特定的文件,并尝试对该文件进行加锁。如果加锁成功,则表示程序是第一个实例,可以继续执行。如果加锁失败,则表示已经有一个实例在运

    2024年02月16日
    浏览(56)
  • 在IDEA同一个窗口中同时打开多个独立项目

    不知道大家在使用Intellij Idea的时候,有没有遇到过类似的问题?自己负责了很多项目,使用idea的时候,经常要在不通的项目代码之间切换来切换去。搜索代码的时候只能搜到当前打开的这个项目代码。 因为这些原因,一些零碎的小项目还是得用Eclipse开发。有时候也会用An

    2024年02月14日
    浏览(114)
  • ROS实现一个节点同时发布订阅多个话题(C++版)

      如果想在一个节点同时发布订阅多个话题就要使用到多线程机制,在C++中如何使用多线程,在C++中开多线程模板已经有了介绍,就是下面这个:    但是有一点需要注意的是,创建节点的涉及到一个主线程,如果想同时发布订阅是不能使用主线程的(也就是不能主线程发

    2024年02月11日
    浏览(38)
  • 多个数据webSocket推送太快导致前端渲染卡顿问题优化

    作者代码写的不怎么样,谅解!主要思路就是把websocket接收到的数据用一个数组暂存起来,达到一定数量一起修改统一渲染,可根据项目数据推送数据的速度适当调解数组大小,然后再加了一个可能一段时间内都到不到数组达标渲染数量,就使用定时器直接做渲染,防止数据

    2024年02月12日
    浏览(49)
  • nuxt3 useFetch封装一个api接口http请求 - 解决刷新页面useFetch无返回

    项目中封装接口请求,并且解决刷新页面useFetch无返回数据问题 刷新页面useFetch无返回数据问题: 浏览器刷新的时候页面没有显示数据,接口data无返回。本身nuxt的useFetch在参数不变的情况下,数据是不会重新从后台接口去请求数据的,会直接拿上一次的结果。但是有实时去后

    2024年02月11日
    浏览(77)
  • 解决多线程环境下单例模式同时访问生成多个实例

    在多线程环境下使用单例模式可能会出现线程安全问题,还有延迟加载问题,这些问题在设计之初需要考虑,保证项目生产上线不影响正常使用 目录 前言 正文 如何满足单例:1.构造方法是private、static方法、if语句判断 解决多线程环境下单例模式问题方法:懒汉式加锁、双重

    2024年02月14日
    浏览(34)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包