2014-10-20 55 views
4

使用Node.js + Express(4)+ Mongoose(使用承諾而不是回調),我無法理清如何清理錯誤處理。使用承諾在Node.js + Express中處理錯誤

我有什麼(而簡化的)是:

app.get('/xxx/:id', function(request, response) { 
    Xxx.findById(request.params.id).exec() 
     .then(function(xxx) { 
      if (xxx == null) throw Error('Xxx '+request.params.id+' not found'); 
      response.send('Found xxx '+request.params.id); 
     }) 
     .then(null, function(error) { // promise rejected 
      switch (error.name) { 
       case 'Error': 
        response.status(404).send(error.message); // xxx not found 
        break; 
       case 'CastError': 
        response.status(404).send('Invalid id '+request.params.id); 
        break; 
       default: 
        response.status(500).send(error.message); 
        break; 
      } 
     }); 
}); 

這裏,在開關「承諾拒絕」部分中,Error是我撲倒了一個潛在的有效ID是錯誤沒有找到,CastError演員到的ObjectId失敗由貓鼬爲無效的id,扔了,500錯誤例如可以通過錯誤輸入throw Error()throw Err()被觸發(引起的ReferenceError:錯誤沒有定義)。

但是像這樣,我的每一條路線都有這個巨大笨拙的開關來處理不同的錯誤。

我該如何集中處理錯誤?不知怎的,交換機可以塞進一些中間件嗎?

(我確實希望我可以在'承諾被拒絕'區塊內使用throw error;重新投擲,但我一直無法使其工作)。

+0

難道你不能只是讓全局錯誤處理函數(它到處都是一樣嗎?),並將它傳遞給每個路由中的'.then(null,...)'? – Bergi 2014-10-20 17:11:17

+0

@Bergi:謝謝 - 我曾想過一個全局錯誤處理函數,我只是覺得應該有一種更「本土」的方式來做事情。全局錯誤處理函數可以正常工作 - 如果您已將它作爲答案,我會接受它! – ChrisV 2014-10-21 06:38:15

+0

@ChrisV你提到的更「原生」的方式是使用基於承諾的路由器,而不是默認的路由器,它會讓你返回Xxx.findById(...)然後檢查是否被拒絕,我認爲spion在一些地方寫了一個點 – 2014-10-21 16:16:56

回答

6

我會創建中間件來處理錯誤。對於404s使用next()。和其他錯誤next(err)

app.get('/xxx/:id', function(req, res, next) { 
    Xxx.findById(req.params.id).exec() 
    .then(function(xxx) { 
     if (xxx == null) return next(); // Not found 
     return res.send('Found xxx '+request.params.id); 
    }) 
    .then(null, function(err) { 
     return next(err); 
    }); 
}); 

404處理器

app.use(function(req, res) { 
    return res.send('404'); 
}); 

錯誤處理程序

app.use(function(err, req, res) { 
    switch (err.name) { 
    case 'CastError': 
     res.status(400); // Bad Request 
     return res.send('400'); 
    default: 
     res.status(500); // Internal server error 
     return res.send('500'); 
    } 
}); 

您可以通過發送類似json的響應在此進一步提高:

return res.json({ 
    status: 'OK', 
    result: someResult 
}); 

return res.json({ 
    status: 'error', 
    message: err 
}); 
+2

當我按照你的建議添加'return next(err)'時,它會得到這個語句,然後就在'等待本地主機'的位置......如果你確信這種方法應該可行,在我的代碼中有其他錯誤,但我不能在我的生活中看到什麼! – ChrisV 2014-10-20 17:28:16

+0

你有一條路由是在處理'404'之後,你是否使用'app.get('/ xxx /編號爲'id',函數(req,res,next)'。 – Jordonias 2014-10-20 17:29:21

+0

我會通過你的nfl-rest看看,謝謝 – ChrisV 2014-10-20 18:10:37