2012-04-30 56 views
22

Tôi đã xem tài liệu về Express và the part describing error handling hoàn toàn không rõ ràng đối với tôi.Làm thế nào để xử lý các ngoại lệ mã trong node.js?

Tôi đã tìm được app chúng đang đề cập đến là một phiên bản createServer(), phải không? Nhưng tôi không có đầu mối làm thế nào để ngăn chặn node.js từ thổi lên quá trình ứng dụng khi một ngoại lệ xảy ra trong khi xử lý một yêu cầu.

Tôi không cần bất cứ điều gì ưa thích thực sự; Tôi chỉ muốn trả lại trạng thái 500, cộng với một phản hồi trống rỗng, bất cứ khi nào có ngoại lệ. Quá trình nút không được chấm dứt chỉ vì có một ngoại lệ chưa được bắt đầu ở đâu đó.

Có một ví dụ đơn giản về cách đạt được điều này không?


var express = require('express'); 
var http = require('http'); 

var app = express.createServer(); 

app.get('/', function(req, res){ 
    console.log("debug", "calling") 
    var options = { 
     host: 'www.google.com', 
     port: 80, 
     path: "/" 
    }; 
    http.get(options, function(response) { 
     response.on("data", function(chunk) { 
      console.log("data: " + chunk); 
      chunk.call(); // no such method; throws here 
     }); 
    }).on('error', function(e) { 
     console.log("error connecting" + e.message); 
    }); 
}); 

app.configure(function(){ 
    app.use(express.errorHandler({ dumpExceptions: true, showStack: true })); 
}); 

app.listen(3000); 

treo toàn bộ ứng dụng, sản xuất traceback

mypath/tst.js:16 
      chunk.call(); // no such method; throws here 
       ^TypeError: Object ... has no method 'call' 
    at IncomingMessage.<anonymous> (/Library/WebServer/Documents/discovery/tst.js:16:18) 
    at IncomingMessage.emit (events.js:67:17) 
    at HTTPParser.onBody (http.js:115:23) 
    at Socket.ondata (http.js:1150:24) 
    at TCP.onread (net.js:374:27) 
+0

'chỉ vì có một ngoại lệ uncaught somewhere.' Quá trình này *** sẽ *** chết nếu có một * uncaught * ngoại lệ. Nếu bạn không muốn nó chấm dứt khi một ngoại lệ xảy ra, hãy nắm bắt ngoại lệ và trả về lỗi 500. – Chad

+2

Bạn có thể quan tâm đến cách không thể hiện: http://stackoverflow.com/questions/4213351/make-node-js-not-exit-on-error – Matt

+0

Tuyệt vời, cảm ơn rất nhiều @Matt! – user124114

Trả lời

2

Bạn có thể dùng xử lý lỗi mặc định mà hiện sử dụng, mà thực sự là connect error handler.

var app = require('express').createServer(); 

app.get('/', function(req, res){ 
    throw new Error('Error thrown here!'); 
}); 

app.configure(function(){ 
    app.use(express.errorHandler({ dumpExceptions: true, showStack: true })); 
}); 

app.listen(3000); 

Cập nhật Đối với mã của bạn, bạn thực sự cần phải nắm bắt lỗi và vượt qua nó để diễn tả như thế này

var express = require('express'); 
var http = require('http'); 

var app = express.createServer(); 

app.get('/', function (req, res, next) { 
    console.log("debug", "calling"); 
    var options = { 
    host:'www.google.com', 
    port:80, 
    path:"/" 
    }; 
    http.get(options, 
    function (response) { 
     response.on("data", function (chunk) { 
     try { 
      console.log("data: " + chunk); 
      chunk.call(); // no such method; throws here 

     } 
     catch (err) { 
      return next(err); 
     } 
     }); 
    }).on('error', function (e) { 
     console.log("error connecting" + e.message); 
    }); 
}); 

app.configure(function() { 
    app.use(express.errorHandler({ dumpExceptions:true, showStack:true })); 
}); 

app.listen(3000); 
+0

Ví dụ của bạn hoạt động (sau khi thêm 'var express = require ('express');'), nhưng thật không may khi tôi làm điều tương tự trong mã của tôi, nó vẫn làm hỏng quá trình. Tôi đã cập nhật câu hỏi với mã mẫu. – user124114

+0

Tôi đã cập nhật câu trả lời cho biết cách ghi lại lỗi và chuyển nó thành express bằng cách sử dụng next(). – 250R

+0

Cảm ơn bạn @ 250R! Thật không may tôi không thể đủ khả năng để xả rác logic mã ở khắp mọi nơi với các cấu trúc như vậy, vì vậy tôi sẽ đi với các giải pháp Matt liên quan đến, trong các ý kiến ​​ở trên. – user124114

38

Nếu bạn thực sự muốn bắt tất cả các trường hợp ngoại lệ và cung cấp một số xử lý khác hơn thoát khỏi quá trình Node.js, bạn cần xử lý sự kiện uncaughtException của Node. Nếu bạn nghĩ về nó, đây là một điều Node, và không phải là một điều Express, bởi vì nếu bạn ném một ngoại lệ từ một số đoạn mã tùy ý, không có đảm bảo Express có thể hoặc sẽ bao giờ nhìn thấy nó, hoặc được trong một vị trí để bẫy nó. Các trường hợp ngoại lệ không tương tác tốt với mã gọi ngược sự kiện không đồng bộ, đó là kiểu nút, ngoại lệ di chuyển lên ngăn xếp cuộc gọi để tìm một khối catch() nằm trong phạm vi tại thời điểm ngoại lệ được ném. với hàm gọi lại chạy khi một số sự kiện xảy ra, sau đó quay lại vòng lặp sự kiện, sau đó khi hàm gọi lại được gọi, nó được gọi trực tiếp từ vòng lặp sự kiện chính và myFunction không còn trên ngăn xếp cuộc gọi; một ngoại lệ, ngay cả khi myFunction có khối thử/nắm bắt, nó sẽ không bắt ngoại lệ.)

Điều này có nghĩa là nếu bạn ném ngoại lệ và không tự mình bắt và bạn làm như vậy một hàm được gọi trực tiếp bởi Express, Express có thể bắt được ngoại lệ n và gọi trình xử lý lỗi mà bạn đã cài đặt, giả sử bạn đã định cấu hình một số phần mềm trung gian xử lý lỗi như app.use(express.errorHandler()). Nhưng nếu bạn ném cùng một ngoại lệ trong một hàm được gọi để phản hồi sự kiện không đồng bộ, Express sẽ không thể bắt được nó. (Cách duy nhất nó có thể bắt nó là lắng nghe sự kiện toàn cầu Node uncaughtException, đó sẽ là một ý tưởng tồi đầu tiên bởi vì đó là toàn cầu và bạn có thể cần sử dụng nó cho những thứ khác, và thứ hai vì Express sẽ không biết yêu cầu là gì liên kết với ngoại lệ.)

Đây là một ví dụ.Tôi thêm đoạn mã này lộ trình xử lý để ứng dụng nhanh hiện có:

app.get('/fail/sync', function(req, res) { 
    throw new Error('whoops'); 
}); 
app.get('/fail/async', function(req, res) { 
    process.nextTick(function() { 
     throw new Error('whoops'); 
    }); 
}); 

Bây giờ nếu tôi ghé thăm http://localhost:3000/fail/sync trong trình duyệt của mình, trình duyệt bãi một chồng gọi (hiển thị express.errorHandler trong hành động). Tuy nhiên, nếu tôi truy cập http://localhost:3000/fail/async trong trình duyệt của mình, trình duyệt sẽ tức giận (Chrome hiển thị thông báo "Không nhận dữ liệu: Lỗi 324, net :: ERR_EMPTY_RESPONSE: Máy chủ đã đóng kết nối mà không gửi bất kỳ dữ liệu nào"). , cho thấy một backtrace trên stdout trong terminal mà tôi gọi nó.

+5

Đây là một câu trả lời thực sự tuyệt vời vì nó không chỉ làm sáng tỏ sự rõ ràng của nó như thế nào mà bắt được các lỗi ngoại lệ và xử lý chúng bằng phần mềm trung gian lỗi (mà là một hành vi mặc định không mong muốn), mà còn vì nó giải thích cách sử dụng 'throw new Error (" ... ") 'trong các hàm async sẽ không kích hoạt phần mềm trung gian lỗi và trên thực tế thậm chí sẽ không bị bắt bởi bất kỳ trình xử lý ngoại lệ nào bao hàm hàm async. Bạn không thể tìm thấy thông tin này ở bất kỳ nơi nào khác. – fthinker

+2

Sử dụng [tên miền] (http://nodejs.org/api/domain.html) là một giải pháp thay thế tốt hơn để bắt 'uncaughtException'. – James

+2

Tên miền đang trong quá trình không được chấp nhận. API thay thế là gì? –

10

Để có thể bắt lỗi không đồng bộ, tôi sử dụng miền. Với Express bạn có thể thử mã này:

function domainWrapper() { 
    return function (req, res, next) { 
     var reqDomain = domain.create(); 
     reqDomain.add(req); 
     reqDomain.add(res); 

     res.on('close', function() { 
      reqDomain.dispose(); 
     }); 
     reqDomain.on('error', function (err) { 
      next(err);    
     }); 
     reqDomain.run(next) 
    } 
} 
app.use(domainWrapper()); 
//all your other app.use 
app.use(express.errorHandler()); 

Mã này sẽ làm cho lỗi không đồng bộ của bạn được chụp và gửi đến xử lý lỗi của bạn. Trong ví dụ này tôi sử dụng express.errorHandler, nhưng nó hoạt động với bất kỳ trình xử lý nào.

Để biết thêm thông tin về tên miền: http://nodejs.org/api/domain.html

+0

Đây là gói npm thực hiện việc này: https://www.npmjs.com/package/express-domain-middleware – pjincz

+0

giải pháp/giải pháp tốt nhất! – felixfbecker

+3

Mô-đun 'miền' đang chờ xử lý. Vì vậy, tôi sẽ không khuyên bạn nên sử dụng nó. – mauvm

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