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

 更新时间:2021年05月11日 10:50:44   作者:前端森林  
这篇文章主要给大家介绍了关于字节跳动面试之如何用JS实现Ajax并发请求控制的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

前言

讲真的,最近也很迷茫。关于技术、关于生活吧。也找了很多在大厂的朋友去聊,想需求一些后期发展的思路。这其中也聊到了面试,聊到了招聘中会给面试者出的一些题目。我正好也好久没面试了,就从中选了几道。最近也会陆续出一系列关于一些面试问题的解析。

今天这道是字节跳动的:

实现一个批量请求函数 multiRequest(urls, maxNum),要求如下:

• 要求最大并发数 maxNum

• 每当有一个请求返回,就留下一个空位,可以增加新的请求

• 所有请求完成后,结果按照 urls 里面的顺序依次打出

这道题目我想很多同学应该都或多或少的见过,下面我会依次从出现的场景、问题的分析到最终的实现,一步步力求深入浅出的给出这道题目的完整解析。

场景

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

应该怎么做?

首先我们来了解一下 Ajax的串行和并行。

基于 Promise.all 实现 Ajax 的串行和并行

我们平时都是基于promise来封装异步请求的,这里也主要是针对异步请求来展开。

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

通过定义一些promise实例来具体演示串行/并行。

串行

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");
});

Promise.all 并发限制

这时候考虑一个场景:如果你的promises数组中每个对象都是http请求,而这样的对象有几十万个。

那么会出现的情况是,你在瞬间发出几十万个http请求,这样很有可能导致堆积了无数调用栈导致内存溢出。

这时候,我们就需要考虑对Promise.all做并发限制。

Promise.all并发限制指的是,每个时刻并发执行的promise数量是固定的,最终的执行结果还是保持与原来的Promise.all一致。

题目实现

思路分析

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

代码实现

function multiRequest(urls = [], maxNum) {
  // 请求总数量
  const len = urls.length;
  // 根据请求数量创建一个数组来保存请求的结果
  const result = new Array(len).fill(false);
  // 当前完成的数量
  let count = 0;

  return new Promise((resolve, reject) => {
    // 请求maxNum个
    while (count < maxNum) {
      next();
    }
    function next() {
      let current = count++;
      // 处理边界条件
      if (current >= len) {
        // 请求全部完成就将promise置为成功状态, 然后将result作为promise值返回
        !result.includes(false) && resolve(result);
        return;
      }
      const url = urls[current];
      console.log(`开始 ${current}`, new Date().toLocaleString());
      fetch(url)
        .then((res) => {
          // 保存请求结果
          result[current] = res;
          console.log(`完成 ${current}`, new Date().toLocaleString());
          // 请求没有全部完成, 就递归
          if (current < len) {
            next();
          }
        })
        .catch((err) => {
          console.log(`结束 ${current}`, new Date().toLocaleString());
          result[current] = err;
          // 请求没有全部完成, 就递归
          if (current < len) {
            next();
          }
        });
    }
  });
}

总结

到此这篇关于字节跳动面试之如何用JS实现Ajax并发请求控制的文章就介绍到这了,更多相关JS实现Ajax并发请求控制内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • JavaScript实现MIPS乘法模拟的方法

    JavaScript实现MIPS乘法模拟的方法

    这篇文章主要介绍了JavaScript实现MIPS乘法模拟的方法,实例分析了JavaScript实现MIPS乘法模拟的运算技巧,需要的朋友可以参考下
    2015-04-04
  • js简单实现调整网页字体大小的方法

    js简单实现调整网页字体大小的方法

    这篇文章主要介绍了js简单实现调整网页字体大小的方法,通过javascript动态修改页面元素样式实现调整网页字体的功能,非常简单实用,需要的朋友可以参考下
    2016-07-07
  • js实现右键弹出自定义菜单

    js实现右键弹出自定义菜单

    这篇文章主要为大家详细介绍了js实现右键弹出自定义菜单,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-09-09
  • js获得相对路径文件并上传到服务器的方法

    js获得相对路径文件并上传到服务器的方法

    由于浏览器的安全限制,Javascript无法直接获取用户上传文件的绝对路径。但是我们可以通过一些技巧来获取文件的相对路径,这篇文章主要给大家介绍了关于js获得相对路径文件并上传到服务器的相关资料,需要的朋友可以参考下
    2023-11-11
  • ECMAScript 数据类型之Number类型

    ECMAScript 数据类型之Number类型

    这篇文章主要介绍了 ECMAScript 数据类型之Number类型,Number类型使用IEEE 754格式表示整数和浮点值,更多相关内容请需要的小伙伴参考下面文章内容
    2022-06-06
  • JavaScript中的JSON转为Python可读取

    JavaScript中的JSON转为Python可读取

    本文主要介绍了JavaScript中的JSON转为Python可读取,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-01-01
  • ES6 对象的新功能与解构赋值介绍

    ES6 对象的新功能与解构赋值介绍

    这篇文章主要介绍了ES6 对象的新功能与解构赋值介绍,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2019-02-02
  • webpack的pitching loader详解

    webpack的pitching loader详解

    这篇文章主要介绍了webpack的pitching loader详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-09-09
  • 面向JavaScript入门初学者的二叉搜索树算法教程

    面向JavaScript入门初学者的二叉搜索树算法教程

    二叉搜索树则是二叉树的一种,但它只允许你在左侧节点储存比父节点小的值,右侧只允许储存比父节点大的值,这篇文章主要给大家介绍了关于JavaScript二叉搜索树算法的相关资料,需要的朋友可以参考下
    2021-09-09
  • javascript 根据歌名获取播放地址和歌词内容

    javascript 根据歌名获取播放地址和歌词内容

    在前几天做在线听歌的过程中,碰到了根据歌名获取播放地址和LRC文件内容的问题,今晚花了几个小时把接口整理了一下
    2009-06-06

最新评论