惰性 promise 的核心是“不立即执行,只在首次 await 或 .then() 时才触发异步操作”,它通过闭包延迟调用 executor、确保单次执行,并代理 promise 方法实现零副作用初始化。

惰性 Promise 的核心是“不立即执行,只在首次 await 或 .then() 时才触发异步操作”,它不是缓存结果的 lazy-promise(那是 memoized),而是延迟初始化 + 单次执行。用 Promise 实现的关键在于:把 executor 函数包裹一层、延迟调用,并确保只执行一次。
延迟初始化:用闭包保存 executor 和状态
Promise 构造函数会立即执行传入的 executor,所以不能直接 new Promise(...)。要实现延迟,得把 executor 存起来,等真正需要时再调用:
- 用一个闭包变量(如
init)保存未执行的初始化逻辑 - 首次调用
then/catch/finally或被await时,才运行 executor 并替换为真实 Promise - 后续调用直接复用已创建的 Promise 实例(自然具备 once 特性)
支持标准 Promise 方法:代理原型链
惰性 Promise 要像原生 Promise 一样可用,就得让实例能响应 .then、.catch、.finally。最简洁的方式是返回一个对象,其方法动态委托给内部 Promise:
- 不继承 Promise(无法 extends Promise 且保持 instanceof),改用属性访问代理
- 首次访问任意 Promise 方法时,触发初始化并缓存真实 Promise
- 之后所有方法调用都转发给该 Promise
实现一个 LazyPromise 工厂函数
下面是一个轻量、可直接使用的实现:
function lazyPromise(executor) {
let promise = null;
let init = () => {
promise = new Promise(executor);
init = () => promise; // 后续调用直接返回已创建的 promise
return promise;
};
return {
then: (onFulfilled, onRejected) => init().then(onFulfilled, onRejected),
catch: (onRejected) => init().catch(onRejected),
finally: (onFinally) => init().finally(onFinally),
// 可选:支持 await(需 Symbol.then)
[Symbol.then]: (onFulfilled, onRejected) => init().then(onFulfilled, onRejected)
};
}
// 使用示例:
const lazyDbConn = lazyPromise((resolve, reject) => {
console.log('正在连接数据库...'); // 这行首次 await 时才打印
setTimeout(() => resolve('DB connected'), 1000);
});
// 此时什么都没发生
console.log('定义完成');
// 第一次 await 才触发 executor
await lazyDbConn; // 输出 "正在连接数据库...",1 秒后解析
// 第二次 await 直接走缓存 Promise(不会重复连接)
await lazyDbConn; // 立即返回 'DB connected'
进阶:支持同步值和错误边界
真实场景中,executor 可能抛出同步错误,或返回同步值。可增强 init 逻辑做 try/catch 包裹,并兼容 Promise.resolve(val):
- 在
init()内部用 try/catch 捕获 executor 抛出的异常,转为 rejected Promise - 若 executor 返回非 Promise 值,用
Promise.resolve()包装 - 这样既符合 Promise A+ 规范,又避免同步崩掉整个懒加载流程
不复杂但容易忽略:真正的惰性在于“零副作用初始化”,只要没消费,就绝不触发异步逻辑——这比单纯用 async/await 封装更克制,适合配置加载、模块按需实例化、昂贵资源预占等场景。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











