MST

星途 面试题库

面试题:JavaScript 函数作为值在并发控制场景下的应用

在一个项目中,需要从多个 API 端点获取数据,每个 API 请求由一个返回 Promise 的函数表示。但由于网络限制,同一时间只能有 5 个请求并发执行。请实现一个函数,接收这些 API 请求函数组成的数组,按照最大并发数 5 进行请求,并在所有请求完成后返回结果数组。
20.9万 热度难度
编程语言JavaScript

知识考点

AI 面试

面试题答案

一键面试
function sendRequests(requests, maxConcurrent = 5) {
    return new Promise((resolve, reject) => {
        if (!Array.isArray(requests) || requests.length === 0) {
            return resolve([]);
        }
        let completedCount = 0;
        const results = new Array(requests.length);
        let currentIndex = 0;
        const executeRequest = () => {
            if (currentIndex >= requests.length && completedCount === requests.length) {
                return resolve(results);
            }
            while (currentIndex < requests.length && completedCount - (requests.length - currentIndex) < maxConcurrent) {
                const index = currentIndex++;
                requests[index]()
                   .then(result => {
                        results[index] = result;
                        completedCount++;
                        executeRequest();
                    })
                   .catch(err => {
                        return reject(err);
                    });
            }
        };
        executeRequest();
    });
}

你可以使用以下方式调用这个函数:

// 示例 API 请求函数
const apiRequest1 = () => new Promise(resolve => setTimeout(() => resolve('Result 1'), 1000));
const apiRequest2 = () => new Promise(resolve => setTimeout(() => resolve('Result 2'), 1500));
const apiRequest3 = () => new Promise(resolve => setTimeout(() => resolve('Result 3'), 2000));
const apiRequest4 = () => new Promise(resolve => setTimeout(() => resolve('Result 4'), 2500));
const apiRequest5 = () => new Promise(resolve => setTimeout(() => resolve('Result 5'), 3000));
const apiRequest6 = () => new Promise(resolve => setTimeout(() => resolve('Result 6'), 3500));

sendRequests([apiRequest1, apiRequest2, apiRequest3, apiRequest4, apiRequest5, apiRequest6], 5)
   .then(results => {
        console.log(results);
    })
   .catch(err => {
        console.error(err);
    });

在上述代码中:

  1. sendRequests 函数接收一个包含 API 请求函数的数组 requests 和最大并发数 maxConcurrent(默认为 5)。
  2. 初始化 completedCount 用于记录已完成的请求数,results 数组用于存储每个请求的结果,currentIndex 用于跟踪当前要执行的请求索引。
  3. executeRequest 函数负责在满足并发限制的情况下,不断执行新的请求。每个请求完成后,更新 results 数组和 completedCount,并递归调用 executeRequest 以执行更多请求。
  4. 当所有请求都完成时,通过 resolve(results) 返回结果数组;如果有任何请求失败,则通过 reject(err) 拒绝 Promise。