返回
Promise + Async&Await + Array.reduce + 函数递归:优雅解决网络/接口请求的依次/排队不间断间隔访问
前端
2024-01-08 12:36:51
需求背景
试想在一个需要频繁更新数据的场景(例如:监控、图表类),常规方法是设置一个间隔 N 秒的定时器 setInterval。但是这种方式存在一个问题,当前一个请求时间过长时(超过了间隔时间),后一个请求就会被阻塞,导致数据更新不及时。
解决思路
为了解决上述问题,我们可以利用 Promise、Async&Await、Array.reduce 和函数递归来实现网络/接口请求的依次/排队不间断间隔访问。具体思路如下:
- 首先,我们将所有的请求封装成一个 Promise 数组。
- 然后,利用 Array.reduce 方法,对 Promise 数组进行依次执行。
- 在每个 Promise 执行时,我们利用 Async&Await 等待其执行完毕,并记录其执行时间。
- 如果当前 Promise 执行时间超过了预设的间隔时间,则在下一个 Promise 执行前,添加一个等待时间,使其与预设的间隔时间相等。
- 通过函数递归,不断重复上述步骤,直到所有的请求都执行完毕。
代码示例
const requests = [
fetch('https://example.com/api/v1/data1'),
fetch('https://example.com/api/v1/data2'),
fetch('https://example.com/api/v1/data3')
];
const interval = 1000; // 预设的间隔时间
const fetchWithInterval = async (requests, interval) => {
const results = [];
const reducePromise = requests.reduce(async (previousPromise, currentRequest) => {
await previousPromise;
const startTime = Date.now();
const response = await currentRequest;
const endTime = Date.now();
const executionTime = endTime - startTime;
if (executionTime > interval) {
await new Promise(resolve => setTimeout(resolve, interval - executionTime));
}
results.push(response);
}, Promise.resolve());
return reducePromise.then(() => results);
};
fetchWithInterval(requests, interval).then(results => {
console.log(results);
});
优点
这种方法具有以下优点:
- 可以确保请求依次/排队执行,不会相互阻塞。
- 可以指定预设的间隔时间,确保请求之间有一定的时间间隔。
- 可以通过函数递归不断重复执行请求,直到所有的请求都执行完毕。
总结
利用 Promise、Async&Await、Array.reduce 和函数递归,可以轻松实现网络/接口请求的依次/排队不间断间隔访问,解决定时器 setInterval 在请求时间过长时的缺陷。这种方法简单易用,并且具有很强的灵活性。