Skip to content

面试题实现网络请求并发限制的管理类

代码地址 /example/net-manager/net-manager.html

背景

2020 年阿里的一个面试题(我自己面试被问过的)

掘金地址: https://juejin.cn/post/6907265963016912909

题目:

实现网络请求并发限制的管理类 NetManager(concurrency), 构造函数传入一个 number,是并发的限制数, 提供 request(url, data) => Promise<res> 方法

javascript
// 实现网络请求并发限制的管理类 NetManager(concurrency),
// 构造函数传入一个number,是并发的限制数,
// 提供 request(url, data) => Promise<res> 方法
// Const obj = new NetManager(5)
// obj.request(“/xxx/sss”, {a: 1})

// net-manager.js
class NetManager {
  constructor(number) {
    if (!(typeof number === 'number' && !Number.isNaN(number))) {
      console.error(`NetManager params typeof number === '${typeof number}', value: ${number}`);
    }

    this.number = number;
    this.queues = [];
    this.caches = [];
  }

  trigger = () => {
    const hits = this.queues.filter((i) => i.isFetch === false);
    hits.forEach((item) => {
      item.isFetch = true;

      item
        .task()
        .then(item.resolve)
        .catch(item.reject)
        .finally(() => {
          const deleteIndex = this.queues.findIndex((del) => del.key === item.key);

          if (deleteIndex !== -1) {
            this.queues.splice(deleteIndex, 1);
          }

          if (this.caches.length > 0) {
            this.queues.push(this.caches.shift());
            this.trigger();
          }
        });
    });
  };

  request = (...reset) => {
    return new Promise((resolve, reject) => {
      // 绑定一个函数并传参
      const task = window.fetch.bind(null, ...reset);

      // 生成一个key值,用于删除队列任务
      const key = Math.random();

      const newItem = {key, isFetch: false, task, resolve, reject};
      if (this.queues.length >= this.number || this.caches.length > 0) {
        this.caches.push(newItem);
      } else {
        this.queues.push(newItem);
        this.trigger();
      }
    });
  };
}
const JSON_PLACEHOLDER = 'https://jsonplaceholder.typicode.com/todos/';

const obj = new NetManager(2);

for (let i = 1; i <= 10; i++) {
  obj
    .request(`${JSON_PLACEHOLDER}${i}`, {credentials: 'include'})
    .then((res) => res.json())
    .then((result) => {
      console.log('result', result);
    })
    .catch((err) => {
      console.error(err);
    });
}
html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <script src="./net-manager.js"></script>
  </body>
</html>

这道题考察什么?

序号描述
1Promise 应用
2逻辑思维能力(算法)
3工作经验

队列任务

批量任务、有规律、有逻辑的执行的时候需要用到

序号描述
1批量文件上传文件切片,批量图片上传(聊天)
2多任务相互依赖比如有三个请求,1、2 和 3,请求 2 依赖 1 3 依赖 2。
3表单校验多个异步校验表单
4发送消息保证消息发送顺序,接收顺序
5计数器聊天软件未读数、已读数、表情回复
6http 并发请求限制

NetManager 类扩展

序号方法类型描述
1push增加可以增加任务
2remove移除移除未执行的 Promise,终止正在执行的 Promise
3update修改,排序调整优先级,比如下载任务的时候,我希望用户看到的区域的图片有限下载
4find查询比如进入会话自动下载图片,先查询是否存在队列,不存在继续下载