MST

星途 面试题库

面试题:JavaScript 箭头函数在异步并发控制及内存管理中的深入应用

在一个高并发的 JavaScript 应用场景中,有多个异步任务需要同时执行,但又要控制并发数量以避免内存溢出等问题。请设计一个方案,利用箭头函数结合合适的异步控制技术(如 Promise.allSettled、队列等)来实现这个需求。并阐述在这种复杂场景下,箭头函数的闭包特性对内存管理可能产生的影响以及如何避免潜在的内存泄漏。
13.8万 热度难度
编程语言JavaScript

知识考点

AI 面试

面试题答案

一键面试

1. 方案设计

function asyncTaskControl(tasks, maxConcurrent) {
    return new Promise((resolve, reject) => {
        const results = [];
        let completedCount = 0;
        const taskQueue = [...tasks];
        const executeTask = () => {
            if (taskQueue.length === 0 && completedCount === tasks.length) {
                resolve(results);
                return;
            }
            if (taskQueue.length === 0) return;
            const task = taskQueue.shift();
            Promise.resolve(task())
              .then(result => {
                    results.push({ status: 'fulfilled', value: result });
                })
              .catch(error => {
                    results.push({ status:'rejected', reason: error });
                })
              .finally(() => {
                    completedCount++;
                    executeTask();
                });
        };
        for (let i = 0; i < Math.min(maxConcurrent, tasks.length); i++) {
            executeTask();
        }
    });
}

// 使用示例
const tasks = [
    () => new Promise(resolve => setTimeout(() => resolve('Task 1'), 1000)),
    () => new Promise(resolve => setTimeout(() => resolve('Task 2'), 2000)),
    () => new Promise(resolve => setTimeout(() => resolve('Task 3'), 1500)),
    () => new Promise(resolve => setTimeout(() => resolve('Task 4'), 3000)),
    () => new Promise(resolve => setTimeout(() => resolve('Task 5'), 2500))
];
const maxConcurrent = 3;

asyncTaskControl(tasks, maxConcurrent)
  .then(results => {
        console.log(results);
    })
  .catch(error => {
        console.error(error);
    });

2. 箭头函数闭包特性对内存管理的影响及避免内存泄漏的方法

影响

  • 引用导致内存驻留:箭头函数的闭包会捕获其定义时所在作用域的变量。如果这些变量引用了较大的对象或 DOM 元素等资源,即使这些资源在逻辑上不再需要,由于闭包的存在,它们依然无法被垃圾回收机制回收,从而导致内存占用持续存在,可能引发内存泄漏。
  • 循环引用风险:在复杂的异步场景中,如果闭包中的变量与其他对象形成循环引用,例如在一个对象的方法中使用箭头函数,箭头函数的闭包又引用了该对象本身,垃圾回收机制难以检测和回收这些循环引用的对象,也会造成内存泄漏。

避免内存泄漏的方法

  • 及时释放引用:在不需要闭包捕获的变量时,手动将其设置为 null,这样垃圾回收机制可以回收相关资源。例如,如果在一个函数中定义了箭头函数,且箭头函数捕获了某个局部变量,当该局部变量不再需要时,将其赋值为 null
  • 使用弱引用:对于一些只希望在对象存活时引用,但又不想阻止其被垃圾回收的情况,可以使用 WeakMapWeakSet。它们的键或值是弱引用,不会阻止对象被垃圾回收,从而避免因闭包导致的内存泄漏。
  • 合理设计作用域:尽量减少箭头函数闭包捕获不必要的变量,将变量的作用域限制在最小范围。避免在箭头函数中引用全局变量或长时间存活的对象,以降低闭包对内存管理的负面影响。