2012-06-21 43 views
27

Tôi muốn viết một hàm trung gian thể hiện để thiết lập một người nghe trên sự kiện 'kết thúc' của phản hồi, nếu sự kiện tồn tại. Mục đích là để làm sạch dựa trên mã phản hồi http mà trình xử lý kết thúc đã quyết định gửi, ví dụ: ghi lại mã phản hồi và rollback/commit của một giao dịch db. tức là, tôi muốn dọn dẹp này được minh bạch cho người gọi cuối.Làm cách nào để nắm bắt sự kiện "kết thúc phản hồi" trong node.js + express?

Tôi muốn làm điều gì đó như sau trong nhanh:

Tuyến middleware

function (req, res, next) { 
    res.on ('end', function() { 
     // log the response code and handle db 
     if (res.statusCode < 400) { db.commit() } else { db.rollback() } 
    }); 
    next(); 
} 

Tuyến:

app.post ("/something", function (req, res) { 
    db.doSomething (function() { 
     if (some problem) { 
      res.send (500); 
     } else { 
      res.send (200); 
     } 
    }); 
} 

Khi tôi cố gắng này, 'kết thúc' xử lý sự kiện không bao giờ được gọi. Tương tự cho res.on('close'), mà tôi đọc trong một bài đăng khác. Các sự kiện như vậy có bị sa thải không?

Cách duy nhất khác mà tôi có thể nghĩ là thực hiện việc này là gói res.end hoặc res.send bằng phiên bản của riêng mình trong phần mềm trung gian tùy chỉnh. Đây không phải là lý tưởng, bởi vì res.endres.send không gọi lại, vì vậy tôi không thể chỉ quấn chúng, gọi ban đầu và sau đó làm điều của tôi dựa trên mã phản hồi đã được đặt khi họ gọi lại cho tôi (vì họ đã thắng ' t gọi lại cho tôi).

Có cách nào đơn giản để thực hiện việc này không?

+0

Tại sao bạn không làm những thứ vệ sinh trước khi 'res.end'? –

+0

Cũng tốt, nhưng tôi muốn làm điều đó như là phần mềm trung gian, tức là không có người xử lý cuối cùng phải lo lắng về việc dọn dẹp. Vì vậy, nếu tôi muốn đăng nhập mã phản hồi kết quả, hoặc rollback/cam kết giao dịch db dựa trên mã phản hồi, tôi muốn điều đó hoạt động một cách trong suốt tới trình xử lý cuối. Vì vậy, tôi đang cố gắng bẫy thực hiện tại một số điểm giữa xử lý kết thúc gọi res.send và yêu cầu được thực hiện. – Jake

+0

Nhưng ** bạn ** đang xác định mã trạng thái:/ –

Trả lời

1

Đọc documentation, đây là chữ ký của res.send:

res.send(body|status[, headers|status[, status]]) 

Có nghĩa là bạn có thể thiết lập tình trạng của riêng mình, như thế này: res.send('some string', 200); hoặc thậm chí chỉ res.send(404);.

Phương thức này là phương pháp bạn sử dụng để gửi phản hồi.

Sau khi được gửi cho khách hàng, bạn không thể truy cập nữa, do đó không có gọi lại.

Đây là điều cuối cùng mà máy chủ của bạn thực hiện. Khi nó đã xử lý yêu cầu, nó sẽ gửi phản hồi.

Tuy nhiên, bạn có thể truy cập vào số trước bạn gửi cho khách hàng. Điều này có nghĩa là bạn có thể:

console.log(res); 
res.send(datas); 

Nếu bạn muốn khôi phục/cam kết, bạn thực hiện khi gọi lại của cơ sở dữ liệu, chứ không phải khi phản hồi biến mất.

+0

Cảm ơn. Từ câu trả lời của bạn, nó có vẻ giống như cách tôi muốn làm những điều chỉ đơn giản là không thể mà không thay thế res.send với phiên bản của riêng tôi mà làm sạch sau đó gọi res.send thực sự. – Jake

+0

Có, 'res.send()' là điều cuối cùng mà ứng dụng của bạn sẽ thực hiện khi xử lý yêu cầu, vì vậy nếu bạn muốn dọn dẹp, bạn phải thực hiện trước :) –

+3

res.on ('header', func) FTW! – Hadesara

38

Lạ lùng thay, dường như phản ứng phát ra một "kết thúc" sự kiện khi phản ứng đã bị đóng: http://sambro.is-super-awesome.com/2011/06/27/listening-for-end-of-response-with-nodeexpress-js/

Mặc dù blog entry này là một chút cũ, sự kiện này vẫn còn tồn tại (Line 836 in lib/http.js), vì vậy tôi giả nó sẽ không biến mất sớm, mặc dù không phải của nút cũng không thể hiện tài liệu đề cập đến nó. Đầu năm 2014, nó đã chuyển đến line 504 on of lib/_http_outgoing.js và vẫn hoạt động.

Nhân tiện, sự kiện "lỗi" trên phản hồi của máy chủ có thể không phải là điều bạn thường muốn xem.

+0

+1 Tôi không thể tìm thấy tài liệu, nhưng mã nguồn hiện tại (tính đến hôm nay) vẫn tăng sự kiện. Cảm ơn! –

+0

Không thể làm cho nó hoạt động với kết thúc hoặc kết thúc hoặc đóng. bất kỳ đề xuất? – Hadesara

+1

res.on ('tiêu đề', func) FTW! – Hadesara

16

Chỉ cần thêm @ phản ứng Amatsuyu của, dưới đây là cách nó nên nhìn:

res.on('finish', function() { 
    // do stuff here 
}); 
+0

Có cách nào để truy cập trạng thái cuối cùng của res trong cuộc gọi lại không? Ví dụ, có thể gọi lại nhìn vào res và kéo ra dữ liệu đã được gửi cho khách hàng? –

+1

Có @MatthewHerbst. Vì trình xử lý sự kiện này đang được xử lý bên trong cuộc gọi app.use, chỉ cần sử dụng cùng một đối tượng "res" từ đó. – weexpectedTHIS

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