promise 的核心是为异步操作提供统一可链式处理的抽象,而非单纯包装回调;封装回调需用 new promise 手动实现,严格判断 err 并分别调用 reject/resolve,node.js 中推荐使用 util.promisify 自动转换,但事件型或多次触发回调不适用单个 promise。

Promise 本身不是用来“包装回调函数”的工具,而是为异步操作提供统一、可链式处理的抽象。但如果你有一个基于回调(callback)的异步函数(比如 Node.js 的 fs.readFile 或老式 API),想让它返回 Promise,核心做法是用 new Promise() 手动封装,把回调的执行逻辑放进 executor 函数里。
用 new Promise 封装回调函数
这是最直接的方式:在 Promise 构造函数中调用原始回调函数,并在成功或失败时分别调用 resolve 或 reject。
- 回调通常形如
fn(...args, callback),其中callback(err, result)是常见 Node.js 风格 - 你需在 executor 中传入符合该签名的回调,在它被调用时判断是否有 error,有则
reject(err),否则resolve(result)
例如封装 setTimeout:
function delay(ms) {
return new Promise(resolve => {
setTimeout(resolve, ms);
});
}
处理带错误参数的回调(Node.js 风格)
很多老 API 使用 (err, data) 回调约定。封装时必须检查 err 是否存在,避免遗漏错误导致 Promise 永远不 reject。
Java JDK 25 来自 OpenJDK 官方归档,版本为 JDK 25,本条下载地址已指向官方 Windows x64 zip 安装包直链,适合调试旧项目或兼容旧版 Java 运行环境。
- 不要只写
resolve(data),要先判断if (err) reject(err) - 推荐使用
util.promisify(Node.js 8+)自动完成这类封装,它内部就是按这个逻辑实现的
手动封装示例:
const fs = require('fs');
const readFile = (path, encoding) => {
return new Promise((resolve, reject) => {
fs.readFile(path, encoding, (err, data) => {
if (err) reject(err);
else resolve(data);
});
});
};
用 util.promisify 快速转换(Node.js 环境)
Node.js 内置的 util.promisify 可直接将遵循 (err, value) 约定的函数转为 Promise 版本,无需手写 new Promise。
- 要求原函数最后一个参数是回调,且回调第一个参数是 error
- 支持为对象方法绑定 this(如
promisify(fs.readFile)) - 也支持自定义 promisifyer,处理非标准回调格式
用法:
const { promisify } = require('util');
const readFile = promisify(fs.readFile);
readFile('./file.txt', 'utf8')
.then(data => console.log(data))
.catch(err => console.error(err));
注意:不是所有回调都适合直接 Promise 化
有些回调是事件型(如 on('data', ...))、多次触发型(如 WebSocket 的 message),或没有明确完成时机(如监听 click)。这类不适合简单封装成单个 Promise,应考虑 AsyncIterator、EventTarget + Promise 组合,或用 once(Node.js)等辅助方法提取首次事件。
- Promise 表达的是“一次性的异步结果”,不是“持续的事件流”
- 对多次回调场景,强行 Promise 化可能导致语义失真或遗漏后续数据
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










