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.inspect
或String
至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,则会看到预期的输出更改。
最终, mscdex和Bergi都说懒惰评估的根本原因。
你所做的事情可能不是一个常见的情况,所以我会避免在将来做,因为它不会出现node.js团队将改变这种行为。