面试中 Promise 如何处理 event loop 🤩🤩

下文以如何回答面试做过总结,想要深入promise和event loop => # JS执行机制你了解多少?一文详解事件循环、微任务、宏任务

Promise回忆

Promise 是同步的,但 .then.catch 是异步执行的。

pending:初始状态,等待中。fulfilled:操作成功完成。rejected:操作失败。

  • 执行机制
    • Promise 接收一个执行器函数,该函数会同步立即执行 ,并接收两个参数:resolvereject,用于改变 Promise 的状态。
    • .then 用于处理成功或失败的结果,.catch 专门处理失败,.finally 无论成功或失败都会执行。
  • 链式调用
    • 每次 .then.catch 都会返回一个新的 Promise,支持链式调用。
    • 重要方法
      • Promise.all(iterable):并发执行多个 Promise,全部成功时返回结果数组;若有一个失败,则返回第一个失败的结果。
      • Promise.race(iterable):返回第一个完成的 Promise 结果(无论成功或失败)。
      • Promise.allSettled(iterable):并发执行多个 Promise,无论成功或失败都返回结果数组。
js 复制代码
const p1 = Promise.resolve(1); 
const p2 = Promise.resolve(2); 
Promise.all([p1, p2]) 
    .then(values => console.log(values)); // [1, 2] 
Promise.race([p1, p2])
    .then(value => console.log(value)); // 1

手写promise.all

js 复制代码
const PromiseAll = (promises) => {
  return new Promise((resolve,reject) => {
    let count = 0;
    let res  = [];
    if(promises.length === 0) return resolve(res)
    promises.forEach((item,index) => {
       Promise.resolve(item)
        .then(data => {
          res[index] = data;
          count++; // 循环次数

          // 都完成 调用resolve
          if(count === promises.length) {
            resolve(res)
          }
        })
        .catch(err => {
          reject(err)
        })
    })
  })
}

可以自己写个 demo:异步按顺序读取三个文件. 使用promise异步 要求每次promise返回,可以使用es6

面题:async/await 和promise,用哪个多

  • Promise:提供了丰富的异步操作方法,适合处理多个异步任务。简单异步操作,方便维护
  • async/await :基于 Promise,使用类似同步的方式处理异步操作。async 标识异步函数,await 将后面的任务作为微任务放入微任务队列。结合 try...catch...finally,代码更易维护。

event loop

在开发中,我们会遇到一些异步操作,比如发起网络请求,进行文件读写,或设定定时器等。这些操作使用同步进行执行,可能导致主线程阻塞,造成程序卡顿。这时候,我们可以使用event loop

event loop 本质是一种循环机制,执行异步代码并且管理调用栈和任务队列之间的交互,确保异步任务正常进行。 他会先创建一个全局执行上下文,按顺序执行完全局代码;再不断循环检查微任务队列,如果有任务,全部执行完,将异步任务放入主线程进行执行;再查任务队列,是否有像定时器,i/o等异步任务完成操作进行任务队列,不断重复。

【执行上下文】包含要执行代码和运行需要的信息(词法环境)。执行完成,被弹出栈并且销毁(垃圾回收机制)

总结来讲: Event Loop 是 JavaScript 处理异步任务的核心机制。

  • 背景:在开发中,异步操作(如网络请求、文件读写、定时器等)如果同步执行,会导致主线程阻塞,程序卡顿。Event Loop 通过循环机制管理调用栈和任务队列,确保异步任务正常执行。
  • 执行流程
    1. 创建全局执行上下文,按顺序执行全局代码。
    2. 检查微任务队列,执行所有微任务。
    3. 将异步任务(如定时器、I/O)放入任务队列,按优先级执行。
    4. 重复上述过程,直到任务队列为空。

执行顺序:同步代码 -> 微任务队列 -> 宏任务队列 -> 进入 idle 状态。

微任务与宏任务

  • 微任务

    • Promise.thenMutationObserverprocess.nextTick
    • 微任务在当前任务结束后立即执行,优先级高于宏任务。
    • process.nextTick() 在微任务中优先,在当前操作完成后立即执行,不会进入事件循环的下一个阶段
    • try catch finlly 后面可以看做是promise.then 方法
    • MutationObserver 用于监听 DOM 的变化,当 DOM 发生变化时,它的回调函数会被触发。它的执行顺序优先于宏任务,但低于同步代码和其他微任务(如 Promise.then
  • 宏任务

    • setTimeoutsetIntervalsetImmediate
    • 宏任务在事件循环的下一个阶段执行。

面试考察event loop怎么思考

个人做法:

  • 1,先全局执行上下文有哪些代码,打印处理
  • 2,遇到微任务,放入微任务队列,执行完;如果调用了其他函数,查看是否是微任务或同步代码,是直接执行;如果是宏任务,等待完成后放入任务队列。
  • 3,任务队列,就按压入事件进行操作。比如,0s 定时比1s先压入,即便1s 代码在前面
  • 但总得了解哪些是宏,哪些是微任务

可以做做下面面试题

js 复制代码
console.log('1');
setTimeout(() => {
    console.log('2');
    Promise.resolve().then(() => {
        console.log('4');
    });
    process.nextTick(() => {
        console.log('3');
    });
});
Promise.resolve().then(() => {
    console.log('5');
});
setTimeout(() => {
    console.log('7');
});
setImmediate(() => {
    console.log('9');
});
console.log('6');

当然大佬可以挑战下面event loop 题,可在评论区留下你的讨论

js 复制代码
console.log(1);
setTimeout(() => {
    console.log(2);
},1000);
new Promise((resolve) => {
    // 1s 后调用resolve,promise状态变成fulfilled 触发`.then()`回调打印 3
    setTimeout(resolve,1000,3) 
}).then((value) => {
    console.log(value);
}).then(() => {
    console.log(4);
});

async function async1() {
    try {
        const v1 = await new Promise((resolve) => {
            resolve(7);
        });
        console.log(v1);
        await async2()
    }catch(e) {
        console.log(e);
    }finally{
        console.log(8);
    }
    console.log(9);
    
}
async1()
async function async2() {
    console.log(5);
    throw 6;
}
console.log(10);,

┻┳|・ω・)问我? 关注点赞,有更多精彩内容,咋们不见不散

相关推荐
勘察加熊人3 分钟前
angular打地鼠
前端·javascript·angular.js
柒@宝儿姐24 分钟前
如何判断一个项目用的是哪个管理器
前端·javascript·vue.js·vue3
齐尹秦1 小时前
什么是 HTML?
前端
uhakadotcom1 小时前
Sentry:你的应用程序的守护者
前端·面试·github
uhakadotcom1 小时前
MCP协议详解:让AI更懂你的数据
算法·面试·github
勘察加熊人1 小时前
fastapi +angular迷宫求解可跨域
前端·fastapi·angular.js
一个处女座的程序猿O(∩_∩)O1 小时前
Vue 计算属性与 Data 属性同名问题深度解析
前端·javascript·vue.js
白晨并不是很能熬夜2 小时前
【JVM】性能监控与调优概述篇
java·jvm·经验分享·后端·面试·求职招聘
TANGLONG2222 小时前
【C++】STL全面简介与string类的使用(万字解析)
java·c语言·开发语言·c++·python·面试·蓝桥杯
随风九天2 小时前
使用 Nginx 进行前端灰度发布的策略与实践
运维·前端·nginx·前端灰度发布