最常用方式是用 new promise 手动封装:在执行器中调用回调,按 err 优先约定用 resolve(data) 或 reject(err);对无错回调如 settimeout 仅 resolve,对事件如图片加载则 onload/resolve、onerror/reject;可写 promisify 工具复用。

在 JavaScript 中,把回调函数封装成 Promise 对象最常用的方式是使用 new Promise() 构造函数手动包装。核心思路是:在 Promise 的执行器(executor)中调用原始的回调函数,并根据成功或失败的结果分别调用 resolve 或 reject。
基本封装模式
适用于典型的 Node.js 风格错误优先回调(callback(err, data))或浏览器 API 的成功/失败双回调:
- 传入的回调函数第一个参数是错误对象(
err),存在即表示失败;第二个参数是正常结果 - 在
new Promise内部调用该回调,并用resolve(data)处理成功,reject(err)处理失败 - 注意要加
if (err) return reject(err),避免成功回调和拒绝同时触发
示例:封装 Node.js 的 fs.readFile
fs.promises,手动封装)
function readFileAsync(path, encoding = 'utf8') {
return new Promise((resolve, reject) => {
fs.readFile(path, encoding, (err, data) => {
if (err) {
reject(err);
} else {
resolve(data);
}
});
});
}
// 使用
readFileAsync('./config.json')
.then(data => console.log(JSON.parse(data)))
.catch(err => console.error('读取失败:', err));
处理只有 success 回调的场景
有些老 API 只提供成功回调(如 setTimeout、addEventListener),没有显式错误通道。此时可忽略 reject,或结合其他机制(如超时)主动拒绝:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 对
setTimeout封装,通常只 resolve,不 reject(它本身不会出错) - 对事件监听(如图片加载),可用
load触发 resolve,error触发 reject - 添加超时控制可提升健壮性,比如 10 秒没响应就 reject
示例:封装图片加载
function loadImageAsync(src) {
return new Promise((resolve, reject) => {
const img = new Image();
img.onload = () => resolve(img);
img.onerror = () => reject(new Error(`图片加载失败: ${src}`));
img.src = src;
});
}
复用封装:通用 promisify 工具函数
如果需要多次封装同类回调函数,可以写一个简易的 promisify 工具(类似 Node.js 内置的 util.promisify):
- 接收一个遵循错误优先约定的函数(如
fn(...args, callback)) - 返回一个新函数,调用时返回 Promise
- 自动把最后一位参数替换为 Promise 执行器中的回调
简易实现:
function promisify(fn) {
return function(...args) {
return new Promise((resolve, reject) => {
fn(...args, (err, result) => {
if (err) reject(err);
else resolve(result);
});
});
};
}
// 使用
const readFileAsync = promisify(fs.readFile);
注意事项与避坑点
- 确保回调只被调用一次 —— Promise 状态一旦改变(fulfilled/rejected)就不可逆
- 不要在 Promise 外部抛出同步错误,否则无法被捕获;应在 executor 内部 try/catch 后 reject
- 避免“忘记 return Promise”,尤其在链式调用中(如
.then()里没返回新 Promise 会导致值穿透) - Node.js 14+ 推荐优先使用内置
fs.promises、timers.promises等,更稳定且支持 AbortSignal
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










