可用promise构造函数封装回调函数,将node.js风格(err, result)回调映射为resolve/reject;对不规范回调需按实际参数调整逻辑;需规避漏错、重复调用、未返回promise等陷阱;node.js 8+可直接用util.promisify自动转换。

可以用 Promise 构造函数把回调函数封装成 Promise,核心是把“成功回调”和“失败回调”分别对应到 resolve 和 reject。
基本包装模式
假设有一个传统异步函数 doAsync(callback),它接受一个形如 (err, result) => {} 的 Node.js 风格回调:
- 如果
err存在,调用reject(err) - 否则调用
resolve(result)
封装写法如下:
function doAsyncPromise() {
return new Promise((resolve, reject) => {
doAsync((err, data) => {
if (err) {
reject(err);
} else {
resolve(data);
}
});
});
}
处理不规范的回调签名
有些老库的回调只传一个参数(比如只有 result 或只有 err),或没有错误优先约定。这时需根据实际 API 文档判断逻辑:
- 若回调只传
result(如setTimeout(cb, ms)),可直接resolve() - 若回调只传
error(如某些事件监听器),则用if (err) reject(err),否则resolve() - 若回调无参(如纯通知型),可
resolve()或resolve(true)表示完成
避免常见陷阱
包装时容易出错的地方:
-
不要漏掉错误分支:即使回调没传 err,也要考虑底层可能抛异常,可用
try/catch包裹调用 -
不要多次调用 resolve/reject:Promise 状态一旦改变就不可逆,但回调函数若被意外触发多次(如事件重复绑定),可能造成未预期行为,建议加标记位或使用
once类机制 -
不要忘记返回 Promise:封装函数必须显式
return new Promise(...),否则调用方无法链式调用
用 util.promisify 快速转换(Node.js 8+)
Node.js 内置了 util.promisify,能自动将符合 Node.js 错误优先约定的函数转为 Promise 版本:
const { promisify } = require('util');
const fs = require('fs');
const readFilePromise = promisify(fs.readFile);
readFilePromise('example.txt', 'utf8')
.then(data => console.log(data))
.catch(err => console.error(err));
它本质就是做了上面的手动封装,但更健壮、支持自定义符号属性(如 customPromisifiedSymbol)。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











