NodeJS与promise.catch和console.log的错误?

时间:2017-06-20 23:34:17

标签: javascript node.js promise console.log

运行以下代码时,我会得到不同的结果,具体取决于我是否console.log("fnError: ", fnError)注释掉了。这对我来说非常不合适。

世界上如何调用console.log影响我的承诺?

function run() {
    var fn = function(){
        throw new Error("incorrect message");
    };

    // returns a promise that should fail with
    // an error object whose .message is "correct message"
    var promisifiedFn = function(){
        return Promise.resolve()
            .then(fn)
            .catch((fnError) => {
                // commenting this out fixes things! //
                console.log("fnError: ", fnError);
                ///////////////////////////////////////

                fnError.message = "correct message";
                throw fnError;
            })
    }

    promisifiedFn().catch((e) => {
        console.log("caught error.message:", e.message);
        console.log("caught error:", e);
    });
}
run();

以上产生:

// fnError:  Error: incorrect message
//     at fn (/Users/sam/dev/ethereum/pennyeth/js/temp.js:18:9)
//     at <anonymous>
//     at process._tickCallback (internal/process/next_tick.js:169:7)
//     ...
// caught error.message: correct message
// caught error: Error: incorrect message
//     at fn (/Users/sam/dev/ethereum/pennyeth/js/temp.js:18:9)
//     at <anonymous>
//     at process._tickCallback (internal/process/next_tick.js:169:7)
//     ...

注意&#34;不正确的消息&#34;被记录。如果你注释掉console.log("fnError: ", fnError),你会得到这个:

// caught error.message: correct message
// caught error: Error: correct message
//     at fn (/Users/sam/dev/ethereum/pennyeth/js/temp.js:18:9)
//     at <anonymous>
//     at process._tickCallback (internal/process/next_tick.js:169:7)
//     ....

运行节点8.0.0

2 个答案:

答案 0 :(得分:2)

这是预期的行为。

记录错误(至少经过util.inspectString)会评估其.stack属性。实例化错误对象时,不会初始化堆栈字符串,但是为了节省内存而延迟构建堆栈字符串。堆栈跟踪将包含错误消息,当您更改.message属性时,它将在堆栈跟踪中反映或不反映,具体取决于是否已创建。

来自the V8 stack trace API description

  

为了提高效率,堆栈跟踪在捕获时不会格式化,而是在第一次访问堆栈属性时按需扫描。

the official node Error documentation

  

当error.stack属性访问时,表示堆栈跟踪的字符串是延迟生成的。

答案 1 :(得分:1)

我能够在下面只有4行重现这个“虫子”。

var e = new Error('first');
console.log(e);
e.message = 'new';
console.log(e);

我尝试过Chrome 59,它没有同样的问题。

然而,Node 7.9.0,Node 8.0.0和Node 8.1.2都存在这个问题。

我在GitHub上报告了一个错误#13832,所以我们会看到它的结果。

更新1 :要显示这不是时间问题,我们可以添加setTimeout次来电

var e = new Error('first');
console.log(e);
setTimeout(() => { e.message = 'new'; }, 1000);
setTimeout(() => console.log(e), 2000);

即使我们等待调用console.log()使问题输出被缓存,问题仍然存在。

更新2 :我收到了GitHub上 mscdex 的回复:

  

这是预期的,因为您所看到的是堆栈跟踪,其中包括生成错误消息后的错误消息。堆栈跟踪是懒惰且仅生成一次(出于性能原因),因此这就是为什么两次都看到相同的输出。

     

如果您将代码更改为输出e.message,您将看到输出的预期变化。

最终, mscdex Bergi 都表示根本原因是懒惰评估。

你正在做的事情可能不是常见的情况所以我将来会避免这样做,因为看来node.js团队不会改变这种行为。