promise包装旧回调的核心是将successcb和errorcb分别映射为resolve和reject,用try...catch捕获回调内异常,校验参数与回调函数类型,标准化错误为error实例,并兼容err-first模式;node.js 15+推荐直接使用util.promisify。

用 Promise 包装旧版回调函数,核心是把“成功回调”和“错误回调”分别对应到 resolve 和 reject,同时确保异常被正确捕获——尤其是防止未处理的错误(如回调里抛出异常、参数非法、异步中出错)导致全局报错或静默失败。
确保回调执行时的异常被捕获
旧 API 常形如 doSomething(data, successCb, errorCb),但 successCb 或 errorCb 内部若抛错,Promise 默认不会拦截。必须在包装时用 try...catch 包住回调调用:
function promisify(oldFn) {
return function(...args) {
return new Promise((resolve, reject) => {
const successCb = (result) => {
try {
resolve(result);
} catch (e) {
reject(e);
}
};
const errorCb = (err) => {
try {
reject(err);
} catch (e) {
reject(e);
}
};
// 传入原始函数:注意调用顺序和参数位置
oldFn(...args, successCb, errorCb);
});
};
}
处理常见错误场景:回调未定义、非函数、多调用
旧接口可能不严谨:比如错误回调没传、successCb 被误写成字符串、或底层多次调用 successCb 导致 Promise 状态重复变更(Promise 一旦 resolve/reject 就不可逆,后续调用会被忽略——这是安全的,但仍建议防御性处理):
- 在传入回调前检查是否为函数,否则立即 reject
- 用布尔标记是否已响应,避免日志混乱(虽不影响 Promise 状态,但利于调试)
- 对 null/undefined 参数做前置校验,提前 reject 而非让老接口崩溃
兼容 Node.js 风格的 (err, data) 回调
如果旧函数用 fn(data, (err, result) => {...}) 形式(如老版 fs.readFile),推荐用现成方案或手动适配:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
function promisifyNodeStyle(fn) {
return function(...args) {
return new Promise((resolve, reject) => {
fn(...args, (err, result) => {
if (err != null) {
reject(err);
} else {
resolve(result);
}
});
});
};
}
注意:Node.js 15+ 已内置 util.promisify,它自动处理 err-first、this 绑定、以及异常捕获,比手写更健壮。
统一错误类型,便于上层 .catch 处理
旧接口错误可能是字符串、Error 实例、甚至 undefined。包装时建议标准化:
- 非 Error 类型的 err(如字符串、数字)转为
new Error(err) - 对 null/undefined 错误,可设默认消息如
"Unknown error" - 保留原始错误的 stack(如果是 Error 实例)
这样上层 .catch(err => console.error(err.message)) 才稳定可靠,不会因 err.message 报错而二次崩溃。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










