最稳妥的做法是让函数同时支持 callback 和 Promise 两种调用方式:通过检查最后一个参数是否为非 null/undefined 的函数来分发,内部统一用 Promise 实现并桥接 callback,保持错误格式一致(Node 风格 err-first),导出时不改名而用 JSDoc 注明双重支持。

JavaScript 中异步 API 升级时,最稳妥的做法是让函数**同时支持 callback 和 Promise 两种调用方式**:有传 callback 就走老路,没传就返回 Promise。这样旧代码无需改动,新代码可直接 await 或链式 .then()。
判断是否传入 callback 参数
核心逻辑在于检查最后一个参数是否为函数且非 null/undefined。注意不能只用 typeof fn === 'function',因为 null 的 typeof 也是 'object',需先排除 null 和 undefined。
- 用 arguments.length 或解构剩余参数(推荐 ES6+)获取末位参数
- 检查该参数是否为 typeof === 'function' 且 !== null
- 若满足,立即执行 callback(err, result);否则构造并返回 Promise
内部统一用 Promise 实现,再桥接 callback
避免维护两套逻辑。把异步操作封装成 Promise(如 fetch、new Promise 包装 setTimeout 等),再在顶层做分发:
- Promise 链结尾用 .then(result => {...}).catch(err => {...}) 处理结果
- 若 callback 存在,就在 then/catch 里调用 callback(null, result) 或 callback(err)
- 若 callback 不存在,直接 return 这个 Promise
保持错误格式一致(特别是 callback 场景)
Node.js 风格的 callback(err, data) 是约定俗成的。即使 Promise 版本 throw Error,callback 版本也必须把错误作为第一个参数传入,而非抛出——否则会触发未捕获异常。
立即学习“Java免费学习笔记(深入)”;
- Promise 中 reject(new Error(...)) → callback 中 cb(error, undefined)
- Promise 中 resolve(data) → callback 中 cb(null, data)
- 避免在 callback 分支里 throw,也不要在 Promise 分支里调用 cb()
导出函数时保留清晰签名
不建议修改函数名(如加 Async 后缀),以免破坏已有引用。可用 JSDoc 注明双重支持:
/**
* @param {string} url
* @param {function(Error, string)=} cb - optional Node-style callback
* @returns {Promise<string>} resolves with response text
*/实际调用示例:
-
旧写法:
fetchData('/api', (err, data) => { ... }) -
新写法:
const data = await fetchData('/api');或fetchData('/api').then(...)


















