MST

星途 面试题库

面试题:JavaScript中Fetch API与Promise的性能优化及原理探究

在高并发场景下,使用Fetch API结合Promise发送多个请求。要求实现请求的并发控制,确保同一时间最多只能有5个请求在执行,当有请求完成后,自动补充新的请求。请分析这种并发控制对性能的影响,以及Fetch API和Promise在这种场景下的底层原理,包括任务队列、事件循环等机制是如何协同工作的。
20.4万 热度难度
编程语言JavaScript

知识考点

AI 面试

面试题答案

一键面试

代码实现

function fetchWithConcurrency(urls, maxConcurrent) {
    let currentIndex = 0;
    const results = [];
    const promises = [];

    function fetchNext() {
        while (promises.length < maxConcurrent && currentIndex < urls.length) {
            const url = urls[currentIndex++];
            const promise = fetch(url)
               .then(response => {
                    results.push(response);
                    return response;
                })
               .catch(error => {
                    results.push(error);
                    throw error;
                })
               .finally(() => {
                    // 完成后补充新请求
                    fetchNext();
                });
            promises.push(promise);
        }

        return Promise.allSettled(promises);
    }

    return fetchNext();
}

// 使用示例
const urls = [
    'https://example.com/api1',
    'https://example.com/api2',
    'https://example.com/api3',
    'https://example.com/api4',
    'https://example.com/api5',
    'https://example.com/api6',
    'https://example.com/api7'
];

fetchWithConcurrency(urls, 5)
   .then(results => {
        console.log('All requests completed:', results);
    });

并发控制对性能的影响

  1. 资源利用:通过限制并发请求数为5,可以避免因过多请求耗尽系统资源(如网络带宽、服务器连接数等)。在高并发场景下,如果没有并发控制,可能导致网络拥塞,所有请求的响应时间都会变长。
  2. 响应时间:对于单个请求而言,并发控制可能会使请求排队等待执行,理论上可能会增加单个请求的等待时间。但从整体来看,由于避免了资源过度竞争,反而可能提升了整体的响应性能,确保每个请求都能在合理时间内获得响应。
  3. 稳定性:合理的并发控制有助于提高系统的稳定性,防止因过多请求导致服务崩溃或响应异常。

Fetch API 和 Promise 在这种场景下的底层原理

  1. Fetch API
    • 原理:Fetch API 是基于Promise的网络请求接口,用于在浏览器中发起HTTP请求。它返回一个Promise对象,该对象在请求完成(无论成功或失败)时被解决。当调用fetch(url)时,浏览器会在网络线程中发起实际的网络请求,同时JavaScript主线程不会被阻塞。
  2. Promise
    • 原理:Promise 是一种处理异步操作的方式,它代表一个尚未完成但预期将来会完成的操作。Promise 有三种状态:pending(进行中)、fulfilled(已成功)和rejected(已失败)。在上述代码中,fetch返回的Promise对象被链式调用,then方法用于处理成功状态,catch方法用于处理失败状态,finally方法无论成功或失败都会执行。
  3. 任务队列与事件循环
    • 任务队列:JavaScript 是单线程的,所有异步操作(如Promise、setTimeout等)都会被放入任务队列。当主线程空闲时,会从任务队列中取出任务执行。在fetch发起请求后,网络请求在后台执行,当请求完成(成功或失败)时,相应的回调函数(thencatch中的函数)会被放入任务队列。
    • 事件循环:事件循环机制不断检查主线程是否空闲,如果空闲则从任务队列中取出一个任务放入主线程执行。在上述代码中,当fetch请求完成后,thencatchfinally中的回调函数会被放入任务队列,等待事件循环将它们放入主线程执行。这样,即使有多个fetch请求并发执行,JavaScript 也能通过任务队列和事件循环有序地处理它们的结果。