2012-06-21 26 views
27

我想編寫一個快速中間件函數,該函數在響應的「結束」事件(如果存在)上設置偵聽器。目的是基於最終處理程序決定發送的http響應代碼進行清理,例如,記錄響應代碼和db事務的回滾/提交。即,我希望這個清理對最終調用者是透明的。如何在node.js + express中捕獲「響應結束」事件?

我想這樣做的明確以下幾點:

路線中間件

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

路線:

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

當我嘗試這一點, '結束'事件處理程序從不被調用。 res.on('close')也是如此,我在另一篇文章中讀到過。這樣的事件是否被解僱?

我能想到的唯一另外一種方式是將res.endres.send與我自己的版本一起包裝在自定義中間件中。這並不理想,因爲res.endres.send不接受回調,所以我不能將它們包裝起來,調用原件,然後根據響應代碼來做我的事情,這些代碼在他們回電時已經設置(因爲他們贏得了'不要打電話給我)。

有沒有簡單的方法來做到這一點?

+0

你爲什麼不前'res.end'做家政的東西? –

+0

這也沒關係,但我想把它當作中間件,即沒有最終處理程序不必擔心清理。所以如果我想記錄結果響應代碼,或者基於響應代碼回滾/提交db事務,我希望它能夠透明地操作結束處理程序。所以我試圖在調用res.send的最終處理程序和正在完成的請求之間的某個時刻捕獲執行。 – Jake

+0

但**你**正在定義狀態碼:/ –

回答

1

documentation,這裏是res.send簽名:

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

這意味着你可以設置自己的狀態,像這樣:res.send('some string', 200);,甚至只是res.send(404);

此方法是您使用發送的響應。

一旦它被髮送到客戶端,你不能再訪問它,所以沒有回調。

這是你的服務器做的最後一件事。一旦它處理了請求,它就發送響應。

但是,您可以在之前訪問它您將其發送給客戶端。這意味着您可以:

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

如果要回滾/提交,你這樣做時,數據庫的回調被調用,而不是當響應了。

+0

謝謝。從你的回答中,這聽起來像我想要做事情的方式根本不可能,而不用我自己的版本替換res.send,然後清理然後調用真正的res.send。 – Jake

+0

是的,'res.send()'是你的應用程序在處理請求時會做的最後一件事情,所以如果你想要進行任何清理,你必須在做之前做到這一點:) –

+3

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

38

奇怪的是,似乎在迴應時發射的響應被關閉的「完成」事件: http://sambro.is-super-awesome.com/2011/06/27/listening-for-end-of-response-with-nodeexpress-js/

儘管這篇博客是有點老了,這個事件仍然存在(Line 836 in lib/http.js),所以我想它不會很快消失,儘管節點或明確的文檔都沒有提及它。 到2014年初,它已經轉移到line 504 on of lib/_http_outgoing.js仍然有效。

順便說一句,服務器響應中的「錯誤」事件可能不是您通常想看到的。

+0

+1我找不到文檔,但當前的源代碼(截至今天)仍然引發了這個事件。謝謝! –

+0

無法完成或結束或關閉。有什麼建議麼? – Hadesara

+1

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

16

只是爲了進一步@ Amatsuyu的迴應,這裏是它應該是什麼樣子:

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

有沒有任何方法可以訪問回調中最終的資源狀態?例如,回調可以查看res並提取發送給客戶端的數據嗎? –

+1

是@MatthewHerbst。由於這個事件監聽器是在app.use調用中進行處理的,因此只需使用相同的「res」對象。 – weexpectedTHIS