2017-03-03 71 views
0

我有一個句柄模板,其中包含兩個部分和一個從上下文中填充的數據。在ExpressJS中使用promise,handlebar和middleware

<h1>Welcome to {{title}}</h1> 
<div id="views"> 
    <div id="place">{{> place}}</div> 
    <div id="player">{{> player}}</div> 
</div> 

現在的ExpressJS路線上我做了以下內容:

var express = require('express'); 
var router = express.Router(); 

var gameDal = require('../app/DAL/gameRepository'); 

router.use('/', (req, res, next) => { 
    if(!res.locals.gameContext) res.locals.gameContext = {}; 

    gameDal.getGame(0).then(game => { 
     res.locals.gameContext.player = game.player; 
     res.locals.gameContext.place = game.place; 
     req.gameTitle = game.title; 
     next(); 
    }); 
}); 

router.get('/', (req, res) => { 
    res.render('home', { "title": req.gameTitle }); 
}); 

module.exports = router; 

的代碼工作正常,但如果我把「下一個()」語句出來的「然後」回調,這兩個部分都與收到的數據正確填充,但「gameTitle」值未定義。

換句話說以下不會因爲模板被渲染的時候替換模板中的{{title}}值時,req.gameTitle值爲「undefined」:

router.use('/', (req, res, next) => { 
    if(!res.locals.gameContext) res.locals.gameContext = {}; 

    gameDal.getGame(0).then(game => { 
     res.locals.gameContext.player = game.player; 
     res.locals.gameContext.place = game.place; 
     req.gameTitle = game.title; 
    }); 

    next(); 
}); 

所以我問題是:

  1. 怎麼會諧音被填入數據和含模板是不是?
  2. 在promise回調中保留「next()」語句會產生什麼影響?
  3. 如果承諾被拒絕會怎樣?

謝謝。

回答

1

next()允許路由繼續。如果您允許該路由在您正確填充res.locals之前繼續,那麼在設置這些值之前可能會進行渲染。這顯然是錯誤的。

因此,當您的工作在中間件中完成並且所有內容都設置爲渲染(或鏈中的下一個中間件)時,您只需要致電next()

這些部分如何填充數據並且包含的​​模板不是?

如果某些事情發生了,而另一些事情卻沒有發生,那麼您可能會碰到一個「運氣不好」的時機問題。當您不等待致電next()時,您正在創建異步操作與渲染中涉及的其他異步操作之間的競爭。由於這些類型的比賽是不可預測的,它可能有用,它可能不會或部分可能起作用。用正確的代碼的想法是刪除所有的比賽,所以它始終工作。

在promise回調中保留「next()」語句會產生什麼影響?

這就是它屬於的地方(在promise回調中),以實現正確和可預測的執行。只有當該回調執行時,您才能真正準備好接下來的所有渲染步驟,只有在您撥打next()並繼續路由時才能完成。

如果承諾被拒絕,該怎麼辦?

你必須有一個拒絕處理程序並決定什麼是正確的響應。如果您將next()放在.then()處理程序中,並且您沒有拒絕處理程序,那麼您的請求將永遠不會發送響應,並且最終瀏覽器會超時。您需要一個.catch()處理程序,該處理程序可能會返回500類型的錯誤頁面。你可以打電話next(err),其中err是某種錯誤,然後你可以有一個通用的錯誤處理中間件,將提供一個錯誤頁面。看到這個答案,以獲取有關快速處理一般的錯誤信息:

Error Handlers in Express

例如,你可以做這樣的事情:

router.use('/', (req, res, next) => { 
    if(!res.locals.gameContext) res.locals.gameContext = {}; 

    gameDal.getGame(0).then(game => { 
     res.locals.gameContext.player = game.player; 
     res.locals.gameContext.place = game.place; 
     req.gameTitle = game.title; 
     next(); 
    }).catch(err => { 
     next(err); 
    }); 

}); 

// Generic error handler for express - should be last middleware defined 
// on app object 
// Note that this has four arguments compared to regular middleware that 
// has three arguments 
// This will handle the next(err) call 
app.use(function (err, req, res, next) { 
    console.error(err.stack) 
    res.status(500).send('Something broke!') 
}); 
+0

@SergioRomero - 這個回答你的問題? – jfriend00