NodeJS与promise.catch和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) // ... 

注意“不正确的信息”被logging。 如果你注释掉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

这是预期的行为。

logging错误(通过util.inspectString至less)会评估它的.stack属性。 当错误对象被实例化时,堆栈string不会被初始化,而是为了节省内存而构build的。 堆栈跟踪将包含错误消息,并且当您更改.message属性时,它将被反映或不在堆栈跟踪中,具体取决于是否已经创build。

从V8堆栈跟踪API描述 :

对于效率,堆栈跟踪在捕获时不是格式化的,而是根据需要,第一次访问堆栈属性。

并从官方节点Error文档 :

访问 error.stack属性时,表示堆栈跟踪的string会延迟生成。

我能够重现这个“错误”,只有4行以下。

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

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

但是,节点7.9.0,节点8.0.0和节点8.1.2都有这个问题。

我报告GitHub #13832上的一个bug,所以我们将看到它是什么。

更新1 :为了显示这不是一个时间问题,我们可以添加setTimeout调用

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

即使我们等待调用console.log() ,这个问题依然存在,这使我相信输出被caching了。

更新2 :我从GitHub的mscdex得到了一个响应:

这是预料之中的,因为你看到的是堆栈跟踪,其中包括错误消息一旦生成。 堆栈跟踪是懒惰地生成的,只有一次(出于性能的原因),所以这就是为什么你两次看到相同的输出。

但是,如果您将代码更改为输出e.message,则会看到预期的输出更改。

最终, mscdexBergi都说懒惰评估的根本原因。

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