面试官:假如有几十个请求,如何去控制并发?

面试官提问:如果现在有几十个请求需要做,你会如何控制并发呢?

我心想:能不能用循环的方式去请求呢,那样好像负载太大,估计直接没了。

要不然,利用Promise模拟一个任务队列,控制好并发的数量,实现请求池的效果,就这么办~

浏览器并发数

浏览器并发连接数是有限的, 一般是4到6个,在10个以内。

(1)http/https 并发数

主流浏览器对 HTTP 1.1 、HTTP 1.0 最大并发连接数目:

(2)websocket 并发数

浏览器额度并发数是有限的,一般是4-6个,在10个以内。这是因为浏览器会限制同一域名下的并发请求数量,以避免对服务器造成过大的压力,所以控制好并发请求的数量尤为重要。

模拟大量请求场景

在开发环境中引入如下代码(笔者在vue文件中引入并调用),此处模拟了100次数据请求。

const ids = new Array(100).fill('') // 模拟 100 个请求

console.time('Request Time') // 计时开始

// 模拟发送请求
const simulateRequests = async () => {
  const requests = ids.map((_, index) => {
    return fetch('https://jsonplaceholder.typicode.com/todos/' + (index + 1))
      .then((response) => response.json())
      .then((data) => console.log(data)) // 打印响应数据
      .catch((error) => console.error('Error:', error))
  })

  // 等待所有请求完成
  await Promise.all(requests)
}

simulateRequests().then(() => {
  console.timeEnd('Request Time') // 计时结束
})

一次性并发上百个请求,要是配置低一点,又或者带宽不够的服务器,直接宕机都有可能,所以我们前端这边是需要控制的并发数量去为服务器解压的。

使用队列解压

什么是队列

先进先出就是队列,push一个的同时就会有一个被shift

如何模拟上图中队列的行为呢?

如何模拟呢?

定义请求池主函数

export const handQueue = (  
  reqs //请求总数,需要是有长度
) => {}

接受一个参数reqs,它是一个数组,包含需要发送的请求。函数的主要目的是对这些请求进行队列管理,确保并发请求的数量不会超过设定的上限。

定义dequeus

const dequeue = () => {  
  while (current < concurrency && queue.length) {  
    current++;  
    const requestPromiseFactory = queue.shift() //出列  
    requestPromiseFactory()  
      .then(() => { //成功的请求逻辑  
      })  
      .catch(error => { //失败  
        console.log(error)  
      })  
      .finally(() => {  
        current--  
        dequeue()  
      });  
  }  
}

这个函数用于从请求池中取出请求并发送。它在一个循环中运行,直到当前并发请求数current达到最大并发数concurrency或请求池queue为空。对于每个出队的请求,它首先增加current的值,然后调用请求函数requestPromiseFactory来发送请求。当请求完成(无论成功还是失败)后,它会减少current的值并再次调用dequeue,以便处理下一个请求。

定义返回请求入队

return (requestPromiseFactory) => {  
  queue.push(requestPromiseFactory) //入队  
  dequeue()  
}

函数返回一个函数,这个函数接受一个参数requestPromiseFactory,表示一个返回Promise的请求工厂函数。这个返回的函数将请求工厂函数加入请求池queue,并调用dequeue来尝试发送新的请求,当然也可以自定义axios,利用Promise.all统一处理返回后的结果。

如何控制

const enqueue = requestQueue(6)//传入最大并发数

  for (let i = 0; i < reqs.length; i++) {
    enqueue(() => fetch('https://jsonplaceholder.typicode.com/todos/' + (i + 1)))
  }

应用

export const handQueue = (
  reqs //请求总数,需要是有长度
) => {
  reqs = reqs || []

  const requestQueue = (concurrency) => {
    concurrency = concurrency || 6 //最大并发数,此处定为6后面可以改
    const queue = [] //请求池
    let current = 0

    const dequeue = () => {
      while (current < concurrency && queue.length) {
        current++
        const requestPromiseFactory = queue.shift() //出列
        requestPromiseFactory()
          .then(() => {
            console.log(1231231)
            //成功的请求逻辑
          })
          .catch((error) => {
            console.log('error1231231')
            //失败
            console.log(error)
          })
          .finally(() => {
            console.log('-----------')
            current--
            dequeue()
          })
      }
    }

    return (requestPromiseFactory) => {
      queue.push(requestPromiseFactory) //入队
      dequeue()
    }
  }

  const enqueue = requestQueue(6)

  for (let i = 0; i < reqs.length; i++) {
    enqueue(() => fetch('https://jsonplaceholder.typicode.com/todos/' + (i + 1)))
  }
}

提示:这里进行请求需要配置环境,可以使H5环境,也可以是开发环境(Vue/React等),但都需要引入axios或者fetch 

Ps

前端并发的主要场景

  1. 页面初始化时加载多个数据资源‌:例如,打开一个网页时,需要从服务器获取用户信息、列表数据和配置信息等。
  2. 依赖数据的级联请求‌:一个请求的结果可能触发多个后续请求。
  3. 批量操作‌:例如批量下载或批量更新数据时,前端会并发多个请求以提高效率。
  4. 实时数据更新‌:例如股票交易平台需要实时更新数据,可能会使用轮询或WebSocket技术。
  5. 第三方服务的集成‌:例如社交媒体分享或地图服务,需要并发请求这些服务的API。

前端并发的主要问题及解决方案

  1. 性能问题‌:并发请求过多可能导致服务器压力增大,响应变慢。
  2. 资源竞争‌:浏览器同时发出的请求数量有限,超出限制会导致请求排队,影响响应速度。
  3. 数据一致性和同步问题‌:多个请求同时修改同一数据源可能导致数据不一致。
  4. 错误处理复杂化‌:并发请求的错误处理更复杂,需要考虑部分请求成功、部分失败的情况。

解决方案包括:

  • 优化请求顺序,减少不必要的并发请求。
  • 使用缓存机制减轻服务器压力。
  • 设计合理的数据同步和状态管理逻辑。
  • 采用错误处理机制,集中处理错误情况。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值