MST

星途 面试题库

面试题:JavaScript 闭包在异步操作链式调用中的应用

假设你需要使用 Promise 实现一系列异步操作的链式调用,且这些操作中涉及到闭包来保存中间状态。请编写代码实现这一需求,并解释闭包在这个过程中是如何维持状态以及对异步编程的影响。
47.4万 热度难度
编程语言JavaScript

知识考点

AI 面试

面试题答案

一键面试

代码实现

function asyncOperation1() {
    return new Promise((resolve) => {
        setTimeout(() => {
            const intermediateState = { data: 'Result from operation 1' };
            resolve(intermediateState);
        }, 1000);
    });
}

function asyncOperation2(prevState) {
    return new Promise((resolve) => {
        setTimeout(() => {
            prevState.data += ' and operation 2';
            resolve(prevState);
        }, 1000);
    });
}

function asyncOperation3(prevState) {
    return new Promise((resolve) => {
        setTimeout(() => {
            prevState.data += ' and operation 3';
            resolve(prevState);
        }, 1000);
    });
}

asyncOperation1()
   .then((state) => asyncOperation2(state))
   .then((state) => asyncOperation3(state))
   .then((finalState) => {
        console.log(finalState.data);
    });

闭包维持状态及对异步编程的影响解释

  1. 闭包维持状态
    • asyncOperation1中,intermediateStatesetTimeout的回调函数中创建。由于setTimeout是异步操作,当asyncOperation1返回Promise时,intermediateState不会被销毁。因为resolve(intermediateState)中的intermediateStatethen回调函数所引用,形成了闭包。
    • asyncOperation2asyncOperation3中,同样通过闭包维持了之前操作产生的prevState。每个asyncOperation函数的prevState参数都引用了上一个操作返回的状态对象,使得状态可以在异步操作链中传递和修改。
  2. 对异步编程的影响
    • 状态管理:闭包使得异步操作链中的状态可以安全地传递和修改,无需全局变量。每个异步操作可以基于前一个操作的结果(状态)进行处理,增强了代码的封装性和可维护性。
    • 错误处理:如果某个异步操作失败(reject),闭包中保存的状态不会丢失上下文,有助于在错误处理中获取相关状态信息,进行针对性的处理。例如,可以在catch块中根据闭包保存的状态记录日志或进行恢复操作。
    • 性能影响:由于闭包会延长变量的生命周期,在异步操作链较长或中间状态对象较大时,可能会占用更多内存。但在合理使用的情况下,这种影响通常是可以接受的,并且通过合理设计中间状态对象的大小和结构,可以有效控制内存使用。