如何在Promise中执行回调?如何简化Express路由Promise样板代码?
在Promise里执行回调主要有两种常用方式,适配不同的代码风格:
使用
.then()和.catch()链式调用:这是Promise的原生用法,.then()接收Promise成功时的结果作为参数,.catch()捕获Promise失败时的错误。示例:// 假设fetchData是返回Promise的异步函数 fetchData() .then(result => { // 成功回调逻辑 console.log('获取数据成功:', result); }) .catch(error => { // 失败回调逻辑 console.error('获取数据失败:', error); });使用
async/await配合try/catch:这种写法更贴近同步代码逻辑,可读性更强。把Promise放在await后面,用try块包裹成功逻辑,catch块捕获错误:async function handleData() { try { const result = await fetchData(); // 成功回调逻辑 console.log('获取数据成功:', result); } catch (error) { // 失败回调逻辑 console.error('获取数据失败:', error); } } handleData();
如果是想把传统的(err, data) => {}格式回调转换成Promise,可以用Node.js的util.promisify或者自行封装,但这属于“回调转Promise”的场景,和你问的“在Promise中执行回调”略有区别。
完全可以实现!这里提供几种不同方案,你可以根据项目需求选择:
方案1:扩展Promise原型(最贴近你想要的写法)
给全局Promise的原型添加自定义respond方法,让所有Promise实例都能直接调用。注意:扩展原生对象原型可能和第三方库存在冲突,适合个人可控的小型项目使用。
// 全局定义Promise的respond方法 Promise.prototype.respond = function(res) { return this .then(data => { res.json({ data }); }) .catch(err => { res.json({ err }); }); }; // 路由中直接使用 router.get('/menu_section', (req, res) => { Section.read(req.body).respond(res); });
这里调整了你原本的respond参数逻辑,因为Promise的成功/失败是通过then/catch分别触发的,让respond接收res作为参数,内部自动处理两种情况,调用起来更简洁。
方案2:编写独立工具函数(避免污染原生原型)
如果不想修改全局Promise对象,可以写一个独立工具函数,把Promise和响应对象传入即可:
// 工具函数 function respond(promise, res) { promise .then(data => res.json({ data })) .catch(err => res.json({ err })); } // 路由中使用 router.get('/menu_section', (req, res) => { respond(Section.read(req.body), res); });
这个方案更安全,不会影响全局环境,适合多人协作或引入大量第三方库的项目。
方案3:async/await + 错误处理中间件(Express最佳实践)
这是Express社区推荐的方式,通过包装函数自动捕获async函数的错误,统一交给全局错误中间件处理:
// 定义async路由处理包装函数 const asyncHandler = fn => (req, res, next) => { Promise.resolve(fn(req, res, next)).catch(next); }; // 路由中使用async/await router.get('/menu_section', asyncHandler(async (req, res) => { const data = await Section.read(req.body); res.json({ data }); })); // 全局错误处理中间件(需放在所有路由之后) app.use((err, req, res, next) => { res.json({ err: err.message || '服务器内部错误' }); });
这种方式不仅避免了重复的then/catch代码,还能统一管理所有路由的错误逻辑,扩展性更强。
内容的提问来源于stack exchange,提问作者darkermuffin

