面试中 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);,

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

相关推荐
flash俊杰几秒前
Electron 桌面应用的进程模型:为什么 fork Next.js standalone
前端
沙蒿同学11 分钟前
我把架构约定编译成了会变红的测试:Wails v2 + Go + Vue3 桌面脚手架实战
前端·后端·github
cpolar技术支持14 分钟前
本地 Playwright 测试报告怎么远程复盘?Trace Viewer 跑起来后,用 cpolar 分享失败现场
前端·自动化测试·测试工具·cpolar·playwright
wordbaby14 分钟前
企业级后台管理系统路由设计与最佳实践指南
前端
胡志辉的博客23 分钟前
【完全开源】IP 纯净度检测 可一键部署到自己的CF
前端·javascript·chrome·ip·chromium
Hilaku1 小时前
作为面试官,我最怕遇到什么样的候选人?
前端·javascript·程序员
TiDi1 小时前
Pinia优化重复请求
前端
web3d5202 小时前
01-用 Leafletjs 10 分钟搭一张水利一张图(Vue3 + Vite 实战)
前端·javascript
晚安日记wanna2 小时前
Vue2 的 defineProperty 差在哪四层追问筛掉九成候选人
前端·vue.js·面试
TiDi2 小时前
吸顶导航交互实现
前端