如何在process.on(unhandledRejection)中打印Promise实际内容而非[Object Promise]
解决Node.js异步异常捕获中unhandledRejection的Promise信息打印问题
问题根源
- 直接将Promise对象做字符串拼接时会调用默认的
toString()方法,只会输出[object Promise],无法展示其内部状态、关联调用栈等有效信息 - 你在
unhandledRejection回调中手动给目标Promise追加.then/.catch处理器时,如果处理器逻辑本身抛出了未捕获的异常,会再次触发unhandledRejection事件,最终形成无限循环打印日志的问题
解决方法
方案1:优先打印错误完整栈信息(推荐)
绝大多数场景下不需要单独打印Promise信息,只需输出reason.stack即可拿到完整的同步+异步调用栈,定位效率更高。你可以在启动Node.js进程时添加--async-stack-traces参数开启完整异步栈追踪,获得的栈信息会更全面。
方案2:使用util.inspect打印Promise内部状态
Node.js内置的util.inspect方法可以读取Promise的隐藏内部属性,包括当前状态、返回值、关联调用栈等信息,不会触发额外的Promise回调,也不会导致循环报错。
修改后的代码示例
const util = require('util'); const fs = require('fs'); const stripIndents = require('common-tags').stripIndents; module.exports = async (client, process, reason, promise) => { const date = new Date(); const formatDate = stripIndents`${(date.getMonth() + 1) .toString().padStart(2, '0')}-${date.getDate() .toString().padStart(2, '0')}-${date.getFullYear() .toString().padStart(4, '0')}` const formatTime = stripIndents`${date.getHours() .toString().padStart(2, '0')}-${date.getMinutes() .toString().padStart(2, '0')}-${date.getSeconds() .toString().padStart(2, '0')}` const dir = './logs'; if (!fs.existsSync(dir)) fs.mkdirSync(dir); // 格式化日志内容 const logContent = `${formatDate} ${formatTime}: 捕获到unhandledRejection 错误详情:${reason.stack || reason} Promise关联信息:${util.inspect(promise, { showHidden: true, depth: 2, compact: false })} =====================分割线===================== `; fs.appendFile(`./logs/${formatDate} UnhandledRejection.log`, logContent, function (err) { if (err) throw err; console.log(`新的UnhandledRejection已记录到日志文件: ${formatDate} UnhandledRejection.log`) }); }
注意事项
- 不要在
unhandledRejection回调中给目标Promise添加任何可能抛出新异常的处理逻辑,避免循环触发事件 - 若需要更完整的异步调用栈,启动Node服务时使用命令:
node --async-stack-traces your-app.js
内容的提问来源于stack exchange,提问作者ComicallyBad
相关产品推荐
相关产品推荐

