前端进阶之旅前端进阶之旅
  • 基础篇HTML/CSS/JS 打底
  • 进阶篇原理与工程化
  • 高频篇面试最常问的那批
  • 精选篇按模块收敛的总结
  • 手写篇常考代码手写实现
  • 面经篇真实面试问题复盘
  • AI 篇NEWAI 时代的前端考点
  • 历年面经NEW按年份追踪真实考点
  • 每日一题每天一道,攒手感
  • 专项自测100 题快速查漏
  • 小程序题库小程序专项刷题
  • 算法题库NEW在线编码即时判题
  • 知识卡片NEW碎片时间过考点
  • 面试题大全常见问题解析
  • AI 答疑NEW随时提问,即时解析
  • AI 模拟面试NEW模拟真实面试 + 报告
  • AI 定制路线NEW按你的简历现排
  • AI 知识地图NEW串起全站知识点
  • 原理篇React / Vue 源码拆解
  • HTTP从报文一路讲到 HTTPS
  • 浏览器渲染、事件循环、进程
  • 计算机基础Linux、网络、操作系统
  • 设计模式23 种模式怎么用
  • Node学习指南从环境搭建到服务端
  • NPM工作流script、依赖与发布
  • Docker容器化部署上手
  • Canvas图形与动画实战
  • 前端系统进阶学习大型项目工程化
  • 前端综合文章长期沉淀的实践文
  • 思维导图知识点全景图
  • 学习路线按图索骥不跑偏
  • AI 热点NEWAI 每日动态
  • 公众号动态公众号历史文章
  • 博客动态站长的技术博客
  • 开发者导航常用工具与文档站
  • 基础篇HTML/CSS/JS 打底
  • 进阶篇原理与工程化
  • 高频篇面试最常问的那批
  • 精选篇按模块收敛的总结
  • 手写篇常考代码手写实现
  • 面经篇真实面试问题复盘
  • AI 篇NEWAI 时代的前端考点
  • 历年面经NEW按年份追踪真实考点
  • 每日一题每天一道,攒手感
  • 专项自测100 题快速查漏
  • 小程序题库小程序专项刷题
  • 算法题库NEW在线编码即时判题
  • 知识卡片NEW碎片时间过考点
  • 面试题大全常见问题解析
  • AI 答疑NEW随时提问,即时解析
  • AI 模拟面试NEW模拟真实面试 + 报告
  • AI 定制路线NEW按你的简历现排
  • AI 知识地图NEW串起全站知识点
  • 原理篇React / Vue 源码拆解
  • HTTP从报文一路讲到 HTTPS
  • 浏览器渲染、事件循环、进程
  • 计算机基础Linux、网络、操作系统
  • 设计模式23 种模式怎么用
  • Node学习指南从环境搭建到服务端
  • NPM工作流script、依赖与发布
  • Docker容器化部署上手
  • Canvas图形与动画实战
  • 前端系统进阶学习大型项目工程化
  • 前端综合文章长期沉淀的实践文
  • 思维导图知识点全景图
  • 学习路线按图索骥不跑偏
  • AI 热点NEWAI 每日动态
  • 公众号动态公众号历史文章
  • 博客动态站长的技术博客
  • 开发者导航常用工具与文档站
首页程序员面试题库Promise executor 同步执行
JSJavaScript异步与 Promise

Promise 构造器中的 executor 是同步执行还是异步执行?

executor 是同步执行的。new Promise 创建实例时,executor 会被立即调用一次;而 then、finally 等回调才是异步进入微任务队列,注意区分。

前端进阶之旅 · 一题精讲更新于 2026.09.05
JavaScript#异步与 Promise#异步编程
先看核心答案读代码示例
理解线索

同步构造,异步通知

  1. executor构造 Promise 时立即同步调用
  2. resolve锁定后续结果,兑现时机取决于传入值
  3. then 回调进入微任务队列在当前代码后执行

executor 的执行时机是同步的,不等于 Promise 的后续处理函数也同步。

核心回答

先记住这个答案

Promise 构造器在执行 new Promise(executor) 时,会当场同步调用 executor,并传入 resolve 和 reject。因此同一段代码里,executor 内的 console.log 一定先于 new Promise 之后的 console.log 输出。executor 中调用 resolve 会把 Promise 标记为 resolved:传入非 thenable 值时状态同步变为 fulfilled;若传入另一个 thenable,Promise 会锁定到它,可能暂时仍处于 pending。无论哪种情况,then 回调都不会同步触发,而会被放入微任务队列,等当前同步代码执行完再运行。若 executor 同步抛出异常,Promise 会被 reject,除非此前已调用过 resolve 或 reject。

  • executor 在构造期间同步调用
  • resolve 不等于立即进入 fulfilled
  • 回调通知异步,异常处理看首次锁定结果

构造函数何时调用 executor

Promise 构造函数在语义上是一个执行器:new Promise(executor) 被求值时,executor 会立刻以 resolveFunc 和 rejectFunc 为参数被调用一次。这个调用发生在 Promise 对象还未赋给任何变量的时刻,所以紧跟在 new Promise 之后的代码必然晚于 executor 的顶层代码运行。例如先输出 1,再 new Promise 中输出 2,再输出 3,控制台会得到 1、2、3。

executor 的返回值没有意义,Promise 实例的状态只能通过 resolve、reject 或同步 throw 改变。若 executor 调用 resolve(value) 且 value 不是 thenable,状态会同步变为 fulfilled(若 value 是 thenable,Promise 会锁定到它,可能暂时保持 pending,最终状态跟随该 thenable);但无论哪种情况,注册到该 Promise 上的 then 回调都不会在此刻运行,而是排入微任务队列。这就是 executor 同步、handler 异步的机制来源,两者分别回答“何时执行构造参数”与“何时执行观察者回调”。

验证 executor 与 then 的执行顺序JavaScript
console.log('start');
new Promise((resolve) => {
  console.log('executor');
  resolve('done');
}).then((value) => console.log('then:' + value));
console.log('end');
查看输出与解释
start
executor
end
then:done

executor 中的日志出现在 start 与 end 之间,证明 executor 是同步调用;then 回调打印在 end 之后,说明 handler 是异步的。

包成 Promise 后,同步工作仍会阻塞当前调用

假设导入工具先解析一份较大的文本,再把解析结果交给页面展示。把解析调用放进 new Promise(resolve => resolve(parse(text))),并不会让解析自动移到后台:调用 parse(text) 和 executor 本身都发生在当前调用栈中,解析结束后构造函数才返回。返回 Promise 只改变结果的消费方式,不会自动改变计算发生在哪个线程。

判断是否能异步让出执行权,要看真正执行工作的 API。定时器可以把工作推迟到后续任务,但回调开始后仍可能阻塞主线程;需要隔离较重计算时,可以根据运行环境使用 Worker。封装已有回调接口则是另一种用途:executor 同步登记回调,等接口产生结果后调用 resolve,调用方通过 then 或 await 消费结果。

resolve 不中断调用,空 executor 永不 settle

executor 是普通函数,调用 resolve(value) 不会像 return 一样结束函数。new Promise(resolve => { resolve(1); console.log("still"); }) 中的日志仍会同步输出。传入普通值会兑现 Promise;传入 thenable 时会采纳它的后续结果,可能暂时仍是 pending。无论结果如何确定,后续观察回调都不会在 resolve 调用里同步执行。

如果执行器和已登记的回调始终不调用 resolve 或 reject,也不触发有效拒绝,这个 Promise 会一直 pending。它是否保留内存取决于可达引用及关联资源,不能只凭 pending 状态判断泄漏。外部超时竞赛可以让调用方停止等待,却不自动取消原工作或清理事件监听器;资源回收需要调用底层清理方法,并释放不再需要的引用。

回答前,多想一步

容易答错的地方

认为 executor 是异步函数
若以为 executor 会等当前同步代码结束后才运行,会误判日志顺序。规范要求在 new Promise 构造时同步调用 executor。可通过在 new Promise 前后放两个 console.log 验证,executor 内的输出总在两个日志之间。
把 resolve 后的 then 当成同步调用
想当然认为先 resolve 后立刻执行 then 回调,忽略了微任务队列。正确顺序是:executor 同步跑完,then 回调在当前任务结束后执行。即使 Promise 已经是 fulfilled 状态,then 也只能异步进入微任务。
试着用自己的话回答

面试官还会怎么问?

executor 先调用 resolve,再同步抛错,会怎样?

例如 resolve(1) 后再同步抛错,结果仍为 1;构造器捕获异常后尝试拒绝,但首次 resolve 已锁定结果。若先 resolve(otherPromise),当前 Promise 仍会跟随 otherPromise,不保证已经 fulfilled;其后同步抛出的异常同样不会覆盖已经锁定的结果。

为什么有人误以为 executor 是异步的?

因为常见 Promise 示例把 setTimeout、fetch 等异步 API 放进 executor。看到回调风格,就误以为整个函数异步。实际上 executor 只是同步注册异步操作的起点,异步是这些 API 自身的行为。

如何快速验证 executor 是否同步?

在代码里依次放 console.log('A'); new Promise(() => console.log('B')); console.log('C');。若输出 A、B、C,则 B 位于构造期间,executor 是同步的;若输出 A、C、B,则 executor 才是异步的。

从一道题,走向一组知识

把知识连起来

异步与浏览器

JavaScript 事件循环如何执行?

executor 与 then 分属同步调用和异步通知,事件循环页可以继续核对微任务顺序。

函数与作用域

JavaScript 中 arguments 对象与函数参数(parameters)有何区别?

executor 接收 resolve 与 reject 两个函数参数,继续理解函数参数绑定及回调调用方式。

放回知识体系中复习JavaScript 进阶知识

参考资料

  • Promise() constructor

示例用于理解所注明的运行环境与边界;延伸学习可结合原文中的更多案例。

本题目录
  1. 先记住这个答案
  2. 构造函数何时调用 executor
  3. 包成 Promise 后,同步工作仍会阻塞当前调用
  4. resolve 不中断调用,空 executor 永不 settle
  5. 容易答错的地方
  6. 面试官还会怎么问
  7. 把知识连起来
读懂,再试着讲出来

先看核心答案,再读代码。最后展开追问,检查自己有没有遗漏边界。

试着回答追问
浏览全部面试题理解原理,也关注真实的使用场景。回到顶部 ↑