JavaScript前端控制网络并发数目的常见方法小结

 更新时间:2023年12月22日 10:40:20   作者:慕仲卿  
控制前端发起请求的并发数,即限制同一时间内进行处理的请求数量,是一种有效的策略,本文将详细介绍前端控制并发数的几种常见做法,希望对大家有所帮助

在现代Web应用开发中,提高用户体验的同时要确保服务器负载平衡是至关重要的。控制前端发起请求的并发数,即限制同一时间内进行处理的请求数量,是一种有效的策略。本文将详细介绍前端控制并发数的几种常见做法,并且提供具体的代码示例。

队列机制

队列是实现并发控制常用的数据结构。它遵循先进先出(FIFO)的原则,能够按照请求到达的顺序逐一处理。

示例:基于 Promise 的请求队列

在JavaScript中,可以利用Promise来实现一个简单的请求队列。下面是一个示例代码:

class PromiseQueue {
  constructor(maxConcurrent) {
    this.maxConcurrent = maxConcurrent;
    this.queue = [];
    this.currentCount = 0;
  }

  add(promiseCreator) {
    return new Promise((resolve, reject) => {
      this.queue.push({
        promiseCreator,
        resolve,
        reject
      });
      this.tryToRun();
    });
  }

  tryToRun() {
    if (this.queue.length === 0 || this.currentCount >= this.maxConcurrent) {
      return;
    }
    this.currentCount++;
    const { promiseCreator, resolve, reject } = this.queue.shift();
    promiseCreator().then(resolve, reject).finally(() => {
      this.currentCount--;
      this.tryToRun();
    });
  }
}

利用此队列可以如下方式控制并发:

// 实例化队列,设置最大并发数为 2
const queue = new PromiseQueue(2);

// 添加请求到队列
queue.add(() => fetch(url1)).then(handleResponse);
queue.add(() => fetch(url2)).then(handleResponse);
queue.add(() => fetch(url3)).then(handleResponse);

在此示例中,只有两个请求会立即执行,第三个请求会等待前两个中的某个完成后再开始。

控制并发的库

市面上有许多专门用于控制并发的JavaScript库,如p-limit, async等。

示例:使用 p-limit 控制并发

p-limit是一个轻量级的库,可以方便地限制并发数:

import pLimit from 'p-limit';

const limit = pLimit(2);

const input = [
    limit(() => fetch(url1)),
    limit(() => fetch(url2)),
    limit(() => fetch(url3)),
    limit(() => fetch(url4)),
];

// 只有 2 个请求被同时处理
Promise.all(input).then(results => {
    // 处理结果
});

在上述代码中,limit函数会保证同时只有两个请求在处理。

XMLHttpRequest的abort方法

在使用XMLHttpRequest(XHR)对象发送请求时,可以在请求数量超过设定的并发限制时调用abort方法来取消请求。

示例:使用XMLHttpRequest和abort控制并发

const MAX_CONCURRENT = 2;
let concurrentCount = 0;
const xhrPool = [];

function fetchWithXhr(url) {
    if (concurrentCount >= MAX_CONCURRENT) {
        setTimeout(() => fetchWithXhr(url), 200); // 200ms 后重试
        return;
    }
    concurrentCount++;
    const xhr = new XMLHttpRequest();
    xhr.open("GET", url);
    xhr.onload = () => {
        handleResponse(xhr.response);
        concurrentCount--;
        if (xhrPool.length > 0) {
            const newXhr = xhrPool.shift();
            fetchWithXhr(newXhr.url);
        }
    };
    xhr.onerror = xhr.onabort = () => {
        concurrentCount--;
    };
    xhr.send();
}

function abortExtraRequests() {
    while (concurrentCount > MAX_CONCURRENT) {
        const xhrToAbort = xhrPool.pop();
        xhrToAbort.abort();
    }
}

// 发起请求
fetchWithXhr("https://api.example.com/data1");
fetchWithXhr("https://api.example.com/data2");
fetchWithXhr("https://api.example.com/data3");

在此示例中,超出并发限制的请求将会被推迟执行,而非立即取消;并且可以使用abortExtraRequests函数对并发数目进行校验,去除超过的部分。

Fetch API的AbortController

Fetch API提供了AbortController接口,通过它可以随时取消一个或多个请求。

示例:使用AbortController控制并发

const MAX_CONCURRENT = 2;
let concurrentCount = 0;
const controllerQueue = new Map();

async function fetchWithAbortController(url) {
    if (concurrentCount >= MAX_CONCURRENT) {
        await new Promise(resolve => setTimeout(resolve, 200)); // 200ms 后重试
        return fetchWithAbortController(url);
    }

    const controller = new AbortController();
    concurrentCount++;
    controllerQueue.set(url, controller);

    try {
        const response = await fetch(url, { signal: controller.signal });
        handleResponse(await response.json());
    } catch (error) {
        // 错误处理
    } finally {
        controllerQueue.delete(url);
        concurrentCount--;
        if (__yourCondition) {
            controllerQueue.get(__specificUrl).abort(); // 取消下一个请求
        }
    }
}

// 发起请求
fetchWithAbortController("https://api.example.com/data1");
fetchWithAbortController("https://api.example.com/data2");
fetchWithAbortController("https://api.example.com/data3");

在这个例子中,AbortController用于取消等待队列中的请求,而且每个请求都有自己的AbortController实例。

通过以上方法,可以有效控制前端并发数,避免服务器过载且优化用户体验。不需修改服务器配置或缩放服务器资源即可实现前端请求的优雅管理。这些策略对于构建响应速度快、资源使用高效的Web应用至关重要。

以上就是JavaScript前端控制网络并发数目的常见方法小结的详细内容,更多关于JavaScript控制网络并发的资料请关注脚本之家其它相关文章!

相关文章

  • 有效提高JavaScript执行效率的几点知识

    有效提高JavaScript执行效率的几点知识

    这篇文章主要介绍了有效提高JavaScript执行效率的几点知识,本文从JavaScript函数、JavaScript作用域、JavaScript字符串、JavaScript DOM操作、DOM重绘、DOM访问、DOM遍历等方面讲解了提高JavaScript执行效率的小技巧,需要的朋友可以参考下
    2015-01-01
  • JS处理数据四舍五入(tofixed与round的区别详解)

    JS处理数据四舍五入(tofixed与round的区别详解)

    下面小编就为大家带来一篇JS处理数据四舍五入(tofixed与round的区别详解)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-10-10
  • 微信小程序实现滑动操作代码

    微信小程序实现滑动操作代码

    这篇文章主要介绍了微信小程序实现滑动操作代码,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-04-04
  • JS动画效果代码3

    JS动画效果代码3

    用js实现的动画效果
    2008-04-04
  • 让复选框只能选择一项的方法

    让复选框只能选择一项的方法

    如何让复选框只能选择一项,实现的方法有很多,在本文为大家详细介绍下,有此需求的朋友可以参考下
    2013-10-10
  • javascript实现保留两位小数的多种方法

    javascript实现保留两位小数的多种方法

    这篇文章主要介绍了javascript实现保留两位小数的多种方法,如果数字的原本小数位数不到两位,那么缺少的就自动补零,感兴趣的小伙伴们可以参考一下
    2015-12-12
  • JavaScript中的对象序列化介绍

    JavaScript中的对象序列化介绍

    这篇文章主要介绍了JavaScript中的对象序列化介绍,JavaScript中的对象序列化是通过JSON.stringify()来实现的,而反序列化则通过JSON.parse()来实现,需要的朋友可以参考下
    2014-12-12
  • p5.js入门教程和基本形状绘制

    p5.js入门教程和基本形状绘制

    本篇文章主要介绍了p5.js入门教程之简介和基本形状绘制,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-03-03
  • 小程序自定义索引菜单

    小程序自定义索引菜单

    这篇文章主要为大家详细介绍了小程序自定义索引菜单,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-07-07
  • javascript实现汉字转拼音代码分享

    javascript实现汉字转拼音代码分享

    这篇文章主要介绍了javascript实现汉字转拼音代码分享,非常的实用,从项目中分离出来的,这里分享给大家,有需要的小伙伴可以参考下。
    2015-04-04

最新评论