【问题标题】:Promise not giving stacktrace承诺不提供堆栈跟踪
【发布时间】:2025-12-11 07:25:02
【问题描述】:

我不熟悉承诺,可能做错了什么。我正在使用 Mongodump 备份 MongoDB 实例。一切正常,但是堆栈跟踪有一个小问题。在一个函数中,应该在主进程中使用 async/await 等待我正在创建一个新的 Promise。在我调用的函数结束时(删掉开头):

backupDB(collection) {
    return new Promise((resolve, reject) => {
        let backupLog = [];
        backupLog.push({
            time: moment(),
            msg: `Backup for ${collection} started`
        });            

        let spawnArguments = [
            '--host', 'localhost',
            '--port', portProd,
            '--collection', collection,
            '--db', dbNameProd,
            '--out', dumpPath
        ];

        const spawnprocess = spawn(mongodumpPath, spawnArguments,
            {shell: true}
        );

        spawnprocess.on('close', (code) => {
            if (code === 0) {
                backupLog.push({
                    time: moment(),
                    msg: `Backup for ${collection} finished`
                });                
                resolve(backupLog);
            } else {
                backupLog.push({
                    time: moment(),
                    msg: `Backup for ${collection} failed`
                }); 
                reject(backupLog);
            }
        });

故意没有定义变量 mongodumpPath(为了演示),但是当我在 try catch 中运行该函数时,没有抛出错误:

    try {
        log = log.concat(await this.backupDB('ops', {regDate: {$gte: {$date: fromDate}, $lte: {$date: toDate}}})); 

    } catch (e) {
        log = log.concat(e);
        return log;
    }

如果我打电话

this.backupDB('ops', {regDate: {$gte: {$date: fromDate}, $lte: {$date: toDate}}})

在控制台中抛出堆栈跟踪。我想这是因为我只在 spawnprocess 发出关闭事件时拒绝了错误。程序之前崩溃了,我怎么能抓住它?

非常感谢! :)

【问题讨论】:

    标签: javascript node.js promise async-await


    【解决方案1】:

    通过以下问题解决了这个问题:

            if (e.stack) {
                log.push({
                    time: moment(),
                    msg: e.stack
                });
            } else {
                log = log.concat(e);
            }
    

    【讨论】:

      【解决方案2】:

      在处理 Promise 时,如果您调用的函数返回一个 Promise,您应该能够将 .catch 附加到函数调用以处理拒绝。

      使用您的代码,它看起来像:

      let backupCall = await this.backupDB('ops', {regDate: {$gte: {$date: fromDate}, $lte: {$date: toDate}}})).catch((error) => console.log(error));
      log = log.concat(backupCall) 
      

      注意附加到 this.backupDB 调用行的catch

      【讨论】:

      • 不应该已经由 try/catch 块处理(见上文)
      • @rStorms 这并不一定会使这个答案出错...... try catch 块也可以工作,但是由于 try catch 块中的唯一逻辑是一个异步调用,在 . catch 使代码更简洁。如果您在 try 块中有多个调用/语句可能会出错并且您希望捕获任何这些错误,那么 try/catch 块将更加实用。在这种情况下,通常应该使用.catch,因为我们只是在寻找那个函数抛出的错误。
      • 完全可以,我没有对此投反对票;)但是并没有解决我的问题
      • 是的,对不起,这是我的错,我错过了一些。为了回答您的问题,我可能是错的,但 log.concat 可能会以某种方式介于您的错误和处理它之间(而不是在其中抛​​出错误),我发布的答案在日志之前没有捕捉到您的错误?