最直接有效的方式是用 Node.js 内置的 util.promisify,它专为标准回调签名(err, result)设计,零配置、防错强;非标准回调需手动封装或通过 custom 属性适配。

最直接有效的方式是用 Node.js 内置的 util.promisify,它专为标准回调签名设计,零配置、防错强、无需手写逻辑。对非标准回调(比如 (data, err) 或单参数),才需手动封装 Promise。
用 util.promisify 快速转换标准 Node.js 回调
适用于形如 fn(...args, (err, result) => {}) 的函数,例如 fs.readFile、fs.stat 等。
- 自动忽略第一个参数
err;有错误时reject(err),否则resolve(result) - 支持绑定上下文:
util.promisify(fs.readFile).bind(fs) - 可直接用于
async/await:
const data = await util.promisify(fs.readFile)('./config.json', 'utf8');
识别并处理非标准回调签名
不是所有回调都按 (err, data) 排列。必须先确认原始函数的回调结构,否则 util.promisify 会误把错误当成功数据返回。
- 查文档或源码,或临时加
console.log(arguments)观察实际传参顺序 - 若回调是
(data, err)形式,需手动判断:
if (err != null) reject(err); else resolve(data); - 若只传一个参数(如
callback(result)),且无显式错误机制,建议约定“假值(null/undefined)表示失败”,或主动注入兜底错误
小程序等环境中的 Promise 化实践
微信小程序、uni-app 等平台原生 API 均为回调式(如 wx.request、uni.showToast),不支持 util.promisify,需手动封装。
- 封装核心逻辑:返回
new Promise((resolve, reject) => { ... }) - 在 success 回调中
resolve(data),在 fail/error 回调中reject(err) - Vant Weapp 已内置部分 Promise 化组件(如
Dialog.show),可直接await - 推荐统一封装成工具函数,例如:
const wxPromisify = (fn) => (...args) => new Promise((resolve, reject) => fn(...args, { success: resolve, fail: reject }));
进阶:自定义 util.promisify.custom
当某个函数不遵循标准回调格式,但你又希望它能被 util.promisify 正确识别,可设置 [util.promisify.custom] 属性。
- 定义一个返回 Promise 的函数,赋值给该 symbol
- 例如适配
doSomething(foo, onSuccess, onError):
doSomething[util.promisify.custom] = (foo) => new Promise((resolve, reject) => doSomething(foo, resolve, reject)); - 之后调用
util.promisify(doSomething)(foo)即可获得标准 Promise 行为

















