运行以下代码时,我会得到不同的结果,具体取决于我是否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
答案 0 :(得分:2)
这是预期的行为。
记录错误(至少经过util.inspect
或String
)会评估其.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团队不会改变这种行为。