2017-06-20 13 views
5

Khi chạy mã sau, tôi nhận được các kết quả khác nhau tùy thuộc vào việc tôi có console.log("fnError: ", fnError) nhận xét hay không. Điều này có vẻ rất với tôi.Lỗi NodeJS với promise.catch và console.log?

Làm thế nào trên thế giới là cuộc gọi đến console.log ảnh hưởng đến lời hứa của tôi?

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(); 

Trên đây sản xuất:

// 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) 
//  ... 

Thông báo "tin nhắn không chính xác" đang được đăng nhập. Và nếu bạn nhận xét ra console.log("fnError: ", fnError) bạn có được điều này:

// 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) 
//  .... 

Chạy nút 8.0.0

+0

Lưu ý: Trong mã ứng dụng thực tế của tôi, tôi _không ghi nhật ký lỗi trước khi thực hiện lại và tôi vẫn nhận được hành vi này. Thật không may tôi không thể tìm ra một ví dụ tối thiểu của nó. –

+0

Điều này thật lạ lùng. Tôi đã thử nó Chrome 59 và nó không có cùng một vấn đề. Nhưng Node 7.9.0, Node 8.0.0 và Node 8.1.2 đều có hành vi này (hoặc lỗi). – styfle

+1

suy nghĩ duy nhất của tôi là console.log là bộ nhớ đệm đối tượng lỗi trước khi giảm dần để stdout. Lưu ý rằng cả hai kết quả "message không chính xác" đều ghi lại cùng một đối tượng. – styfle

Trả lời

2

Đây là hành vi mong đợi.

Ghi nhật ký lỗi (ít nhất là util.inspect hoặc String) đánh giá thuộc tính .stack của nó. Chuỗi ngăn xếp không được khởi tạo khi đối tượng lỗi được khởi tạo, nhưng được xây dựng một cách lười biếng để tiết kiệm bộ nhớ.Theo dõi ngăn xếp sẽ bao gồm thông báo lỗi và khi bạn thay đổi thuộc tính .message, nó sẽ được phản ánh hoặc không theo dấu vết ngăn xếp tùy thuộc vào việc đã tạo ra hay chưa.

Từ the V8 stack trace API description:

Đối với hiệu quả ngăn xếp dấu vết không được định dạng khi họ đang bị bắt nhưng theo yêu cầu, lần đầu tiên chồng sở hữu được truy cập.

và từ the official node Error documentation:

Chuỗi đại diện cho stack trace được lười biếng tạo ra khi tài sản error.stack là truy cập.

+0

Tại sao Chrome có hành vi khác với Node.js? Nút có thực hiện tối ưu hóa này và chrome không? – styfle

+0

@styfle Tôi chưa thử nó, nhưng tôi nghi ngờ sự khác biệt chỉ trong 'console.log' và không phải' error.stack' – Bergi

+1

@styfle Tôi có thể tạo lại nó trong Chrome khi truy cập rõ ràng '.stack'. Nhưng thực tế, 'console.log (e)' chỉ hiển thị thông điệp được cập nhật. – Bergi

1

tôi đã có thể tái sản xuất này "lỗi" với chỉ 4 dòng dưới đây.

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

Tôi đã dùng thử Chrome 59 và không có sự cố tương tự.

Tuy nhiên, Node 7.9.0, Node 8.0.0 và Node 8.1.2 đều có sự cố này.

Tôi đã báo cáo là lỗi trên GitHub #13832 vì vậy chúng tôi sẽ xem điều gì xảy ra.

Cập nhật 1: Để hiển thị này không phải là một vấn đề thời gian, chúng ta có thể thêm setTimeout cuộc gọi

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

Vấn đề vẫn tồn tại ngay cả khi chúng tôi chờ đợi để gọi console.log() mà làm cho tôi tin rằng sản lượng được lưu trữ.

Cập nhật 2: Tôi đã nhận một phản hồi từ mscdex trên GitHub:

này là bình thường vì những gì bạn đang thấy là vết đống, trong đó bao gồm các thông báo lỗi khi nó đã được tạo ra. Dấu vết ngăn xếp được tạo ra một cách lười biếng và chỉ một lần (vì lý do hiệu suất), vì vậy đó là lý do tại sao bạn thấy cùng một đầu ra cả hai lần.

Nếu bạn thay đổi mã của mình thành e.message đầu ra, bạn sẽ thấy thay đổi được mong đợi trong đầu ra.

Cuối cùng, cả hai mscdexBergi đang nói đến nguyên nhân gốc rễ là đánh giá lười biếng.

Điều bạn đang làm có lẽ không phải là một kịch bản phổ biến vì vậy tôi sẽ tránh thực hiện nó trong tương lai vì nó không xuất hiện nhóm node.js sẽ thay đổi hành vi này.

+0

Tôi vẫn gặp phải vấn đề này trong mã ứng dụng của tôi, điều này tương tự nhưng không thực hiện 'console.log' , nghĩa là tôi nhận được thông báo lỗi "cũ". –

Các vấn đề liên quan