在JavaScript编程中,批量请求函数`multiRequest`的实现是一个常见的面试题目,它涉及到异步操作、并发控制和数组处理等多个知识点。这个函数的主要目的是在限制最大并发数的前提下,发送一组HTTP请求,并确保请求结果的顺序与输入URL的顺序一致。
我们需要理解题目中的几个关键概念:
1. **并发数**:指同一时间处理的任务数量,这里指同时进行的HTTP请求。
2. **最大并发数**(maxNum):用户指定的最大同时发送的请求数量。
3. **按顺序打印结果**:所有请求完成后的结果应按照`urls`数组的顺序依次输出。
为了实现`multiRequest`函数,我们可以使用Promise和队列数据结构。以下是一个可能的实现方式:
```javascript
function multiRequest(urls, maxNum) {
const result = [];
const queue = [];
// 创建一个Promise,用于处理单个请求
function request(url) {
return new Promise((resolve, reject) => {
// 使用fetch或axios等库发送请求
fetch(url).then(response => response.json()).then(data => {
resolve({ url, data });
}).catch(error => {
reject({ url, error });
});
});
}
// 发送请求并处理结果
function sendRequests() {
while (queue.length && queue.length < maxNum) {
const url = urls.shift();
if (url) {
queue.push(request(url));
}
}
// 如果有请求在处理,处理完成后继续发送
if (queue.length) {
Promise.all(queue.slice(0)).then(responses => {
responses.forEach(r => {
result.push(r);
queue.shift(); // 移除已完成的请求
sendRequests(); // 发送新的请求
});
}).catch(errors => {
console.error('请求出错:', errors);
});
}
}
// 开始发送请求
sendRequests();
// 返回一个Promise,等待所有请求完成
return new Promise((resolve, reject) => {
const allRequestsFinished = () => {
if (urls.length === 0 && queue.length === 0) {
resolve(result);
} else {
setTimeout(allRequestsFinished, 100); // 检查间隔,防止阻塞
}
};
allRequestsFinished();
});
}
```
在这个实现中,我们创建了一个内部的`request`函数来处理单个URL的请求,并将其结果包装为Promise。然后,我们创建了一个`queue`数组来保存待处理的请求。`sendRequests`函数负责发送不超过`maxNum`个请求,并在每个请求完成后更新结果和队列状态。`multiRequest`函数返回一个Promise,等待所有请求完成后再解析结果。
此函数的运行逻辑如下:
1. 遍历`urls`数组,将未处理的URL添加到队列中,直到达到最大并发数。
2. 当有请求完成时,从队列中移除该请求,并发送新的请求,保持最大并发数不变。
3. 当所有URL都被处理且队列为空时,表示所有请求都已完成,解析结果。
通过这样的设计,我们可以确保在控制并发数的同时,结果始终按照URL的输入顺序输出。
请注意,这个实现使用了`fetch` API来发送HTTP请求,如果你的环境不支持或需要使用其他库(如axios),可以将`request`函数替换为相应的API调用。此外,这个实现没有处理超时或其他高级错误处理,实际应用中可能需要根据需求进行扩展。