JavaScript如何利用Promise控制并发请求个数

一、场景

假设现在有这么一种场景:现有 30 个异步请求需要发送,但由于某些原因,我们必须将同一时刻并发请求数量控制在 5 个以内,同时还要尽可能快速的拿到响应结果。

如图所示:

上图这样的排队和并发请求的场景基本类似,窗口只有三个,人超过三个之后,后面的人只能排队了。

二、串行和并行

  • 串行:一个异步请求完了之后在进行下一个请求
  • 并行:多个异步请求同时进行

串行举例:

var p = function () {
  return new Promise(function (resolve, reject) {
    setTimeout(() => {
      console.log("1000");
      resolve();
    }, 1000);
  });
};
var p1 = function () {
  return new Promise(function (resolve, reject) {
    setTimeout(() => {
      console.log("2000");
      resolve();
    }, 2000);
  });
};
var p2 = function () {
  return new Promise(function (resolve, reject) {
    setTimeout(() => {
      console.log("3000");
      resolve();
    }, 3000);
  });
};

p()
  .then(() => {
    return p1();
  })
  .then(() => {
    return p2();
  })
  .then(() => {
    console.log("end");
  });

如示例,串行会从上到下依次执行对应接口请求。

并行举例:

通常,我们在需要保证代码在多个异步处理之后执行,会用到:

Promise.all((promises: [])).then((fun: function));

Promise.all可以保证,promises数组中所有promise对象都达到resolve状态,才执行then回调。

var promises = function () {
  return [1000, 2000, 3000].map((current) => {
    return new Promise(function (resolve, reject) {
      setTimeout(() => {
        console.log(current);
      }, current);
    });
  });
};

Promise.all(promises()).then(() => {
  console.log("end");
});

这时候考虑一个场景:

如果你的promises数组中每个对象都是http请求,而这样的对象有几十万个。
那么会出现的情况是,你在瞬间发出几十万个http请求,这样很有可能导致堆积了无数调用栈导致内存溢出。
这时候,我们就需要考虑对Promise.all做并发限制。
Promise.all并发限制指的是,每个时刻并发执行的promise数量是固定的,最终的执行结果还是保持与原来的Promise.all一致。

三、代码实现

整体采用递归调用来实现:最初发送的请求数量上限为允许的最大值,并且这些请求中的每一个都应该在完成时继续递归发送,通过传入的索引来确定了urls里面具体是那个URL,保证最后输出的顺序不会乱,而是依次输出。

代码:

function multiRequest(urls, maxNum) {
 const len = urls.length; // 请求总数量
 const res = new Array(len).fill(0); // 请求结果数组
 let sendCount = 0; // 已发送的请求数量
 let finishCount = 0; // 已完成的请求数量
 return new Promise((resolve, reject) => {
     // 首先发送 maxNum 个请求,注意:请求数可能小于 maxNum,所以也要满足条件2
     // 同步的 创建maxNum个next并行请求 然后才去执行异步的fetch 所以一上来就有5个next并行执行
     while (sendCount < maxNum && sendCount < len) {
         next();
     }
     function next () {
         let current = sendCount ++; // 当前发送的请求数量,后加一 保存当前请求url的位置
         // 递归出口
         if (finishCount >= len) {
         // 如果所有请求完成,则解决掉 Promise,终止递归
             resolve(res);
             return;
         }
         const url = urls[current];
         fetch(url).then(result => {
             finishCount ++;
             res[current] = result;
             if (current < len) { // 如果请求没有发送完,继续发送请求
                 next();
             }
         }, err => {
             finishCount ++;
             res[current] = err;
             if (current < len) { // 如果请求没有发送完,继续发送请求
                 next();
             }
         });
     }
 });
}

总结:

代码在while循环处创建了maxNum个"请求窗口"来进行请求,从而达到并行效果,然后next函数中进行异步请求,然后通过在.then里面进行递归进行新请求的调用,实现"一个窗口只进行一个请求,当这个请求执行完成后才进行下一个请求"(每个窗口串行执行,maxNum个窗口并行执行)。

到此这篇关于JavaScript如何利用Promise控制并发请求个数的文章就介绍到这了,更多相关js用Promise控制并发请求内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

参考链接

1、https://www.jb51.net/article/211898.htm

2、https://www.jb51.net/article/212277.htm

(0)

相关推荐

  • js利用递归与promise 按顺序请求数据的方法

    问题:项目中有一个需求,一个tabBar下面如果没有内容就不让该tabBar显示,当然至于有没有内容,需要我们通过请求的来判断,但是由于请求是异步的,如何让请求按照tabBar的顺序进行? 方案:我们可以将promise变成下一个请求,可以利用递归来实现 实施: //定义初始数据 requestlist就像tabBar列表 let requestlist = [1, 2, 3, 4, 5, 6, 7,8,9]; //每个tabBar的返回数据使用reslist装起来 let reslist =

  • 用Promise解决多个异步Ajax请求导致的代码嵌套问题(完美解决方案)

    问题 前端小同学在做页面的时候,犯了个常见的错误:把多个Ajax请求顺序着写下来了,而后面的请求,对前面请求的返回结果,是有依赖的.如下面的代码所示: var someData; $.ajax({ url: '/prefix/entity1/action1', type: 'GET' , async: true, contentType: "application/json", success: function (resp) { //do something on response

  • promise处理多个相互依赖的异步请求(实例讲解)

    在项目中,经常会遇到多个相互依赖的异步请求.如有a,b,c三个ajax请求,b需要依赖a返回的数据,c又需要a和b请求返回的数据.如果采用请求嵌套请求的方式自然是不可取的.导致代码难以维护,如何请求很多.会出现很多问题. Promise就是解决多个异步请求的问题. Promise是ES6提供的一个对象,用来传递异步操作的消息. Promise有三种状态:Pending(进行中).Resolved(已完成,又称 Fulfilled)和 Rejected(已失败). 直接上代码.有a,b请求,b依赖

  • 在vue项目中promise解决回调地狱和并发请求的问题

    场景需求: 需要同时请求5个接口 都请求成功后执行下一步操作 解决方法: 定义一个变量i=5,请求成功一个接口,让i–,直到i=0时执行下一个操作,否则不执行 axios.all 并发请求,.then(axios.spread(function(callback1, callback2)){}) promise.all 并发请求,.then(function([callback1, callback2]){}) 1.回调地狱: 函数作为参数层层嵌套 代替的为.then的链式操作 2.promis

  • 利用Promise自定义一个GET请求的函数示例代码

    写在最前面 近期 review 自己以前的代码的时候,看到 promise 的使用方法,用的比较模糊.含义不清,用法凌乱,这里重新温习一下基础知识. 前言 JavaScript 是单线程工作,但是浏览器是多线程的.为了更好的完成我们程序的任务.Promise 异步的操作就由此诞生了. 一个 Promise 就是一个代表了异步操作最终完成或者失败的结果对象. 怎么使用? 语法 基本 new Promise( function(resolve, reject) {...} /* executor *

  • JavaScript如何利用Promise控制并发请求个数

    一.场景 假设现在有这么一种场景:现有 30 个异步请求需要发送,但由于某些原因,我们必须将同一时刻并发请求数量控制在 5 个以内,同时还要尽可能快速的拿到响应结果. 如图所示: 上图这样的排队和并发请求的场景基本类似,窗口只有三个,人超过三个之后,后面的人只能排队了. 二.串行和并行 串行:一个异步请求完了之后在进行下一个请求 并行:多个异步请求同时进行 串行举例: var p = function () { return new Promise(function (resolve, reje

  • JavaScript使用Promise实现并发请求数限制

    目录 没有Promise的并发请求 使用Promise限制并发请求 使用Promise实现并发请求数限制 总结 没有Promise的并发请求 在Web开发中,我们经常需要发起多个异步请求来获取数据.例如,我们可能需要从服务器获取一些用户信息.文章内容.评论列表等等.如果我们使用的是传统的JavaScript回调函数,可能会写出类似下面这样的代码: function getUsers(callback) { fetch('https://example.com/users', (response)

  • Promise面试题详解之控制并发

    前言 在写这篇文章的时候我有点犹豫,因为先前写过一篇类似的,一道关于并发控制的面试题,只不过那篇文章只给出了一种解决方案,后来在网上又陆续找到两种解决方案,说来惭愧,研究问题总是浅尝辄止,所以今天便放在一起,借着这道面试题再重新梳理一下. 题目是这样的: 有 8 个图片资源的 url,已经存储在数组 urls 中(即urls = ['http://example.com/1.jpg', -., 'http://example.com/8.jpg']),而且已经有一个函数 function loa

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

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

  • 利用js实现Ajax并发请求限制请求数量的示例代码

    出现问题描述:当不确定异步请求个数时,为防止当一瞬间发生上百个http请求时,导致堆积了无数调用栈进而导致内存溢出问题. 要求:将同一时刻并发请求数量控制在3个以内,同时还要尽可能快速的拿到响应的结果. 同面试问题: 实现一个批量请求函数 multiRequest(urls, maxNum),要求如下: 要求最大并发数 maxNum 每当有一个请求返回,就留下一个空位,可以增加新的请求 所有请求完成后,结果按照 urls 里面的顺序依次打出 1.基于Promise.all实现Ajax的串行和并行

  • 如何基于JS实现Ajax并发请求的控制详解

    目录 前言 Ajax的串行与并行 Ajax的并发请求控制的两大解决方案 基于Promise递归实现 基于Class实现 代码展示 总结 前言 最近看到一个面试题,当然了,就是这篇文章的标题,Ajax的并发请求的控制,感觉挺有意思的,在社区看了下,应该是字节的面试题,也挺多大佬对这个进行了总结,都看了下,于是自己也想试着总结下,代码文末会全部贴出,如有不足,请指出! Ajax的串行与并行 串行:一般业务需求是下个接口需要用到上个接口的返回的数据,前端常用的请求库是Axios,本身就是基于Promi

  • 字节跳动面试之如何用JS实现Ajax并发请求控制

    前言 讲真的,最近也很迷茫.关于技术.关于生活吧.也找了很多在大厂的朋友去聊,想需求一些后期发展的思路.这其中也聊到了面试,聊到了招聘中会给面试者出的一些题目.我正好也好久没面试了,就从中选了几道.最近也会陆续出一系列关于一些面试问题的解析. 今天这道是字节跳动的: 实现一个批量请求函数 multiRequest(urls, maxNum),要求如下: • 要求最大并发数 maxNum • 每当有一个请求返回,就留下一个空位,可以增加新的请求 • 所有请求完成后,结果按照 urls 里面的顺序依

  • 深入理解JS中的Promise.race控制并发量

    目录 开篇 一.Promise.race 二.并发效果展示 三.代码 总结与思考 开篇 比如在开发中会进行一系列的网络请求,但是有些情况需要控制一下网络请求请并发量.这里简单的用 Promise.race 及 await 的特性来理解一下,如何对任务的并发量进行控制. 一.Promise.race Promise.race 作用就是将多个异步任务包裹起来,当有一个完成的话,那么就会触发 then 事件.除了这个不错的特性方法外,await 这个关键字也比较有用,可以这样理解,await 后面的代

随机推荐