我试图清理我的app.js代码,并在一个app.use方法中适合从数据库检索到的所有res.locals。我这样做的那一刻,我的应用程序崩溃了,错误是未定义res.locals,从而阻止了嵌套在另一个视图(标题)中的ejs视图(navbar)的呈现。
如果我这样设置全局变量,一切都会很好
//app.js
var express = require("express"),
app = express(),
...
...
// DB models import
var TranslationService = require("./models/translationservice"),
Language = require("./models/language"),
User = require("./models/user");
// ROUTES import (+ use at the bottom!)
var indexRoutes = require("./routes/index.js"),
translationServiceRoutes = require("./routes/translationservice.js"),
languageRoutes = require("./routes/language.js")
// APP config
...
// USER PASSPORT config
...
app.use(function(req,res,next){
res.locals.currentUser = req.user;
res.locals.success = req.flash('success');
res.locals.error = req.flash('error');
next();
});
app.use(function(req,res,next){
TranslationService.find({}, function(err, foundItem) {
if (err || !foundItem) {
console.log(err);
} else {
res.locals.translationServiceData = foundItem;
next();
}
});
});
app.use(function(req,res,next){
Language.find({}, function(err, foundItem) {
if (err || !foundItem) {
console.log(err);
} else {
res.locals.languageData = foundItem;
next();
}
});
});
// ROUTES use
app.use("/", indexRoutes);
app.use("/languages", languageRoutes);
app.use("/translation-services", translationServiceRoutes);
server.listen(3000, function () {
console.log("server has started");
});
我想使我的代码更加干燥,并将所有res.locals合并为一个app.use方法。像这样:
app.use(function(req,res,next){
res.locals.currentUser = req.user;
res.locals.success = req.flash('success');
res.locals.error = req.flash('error');
TranslationService.find({}, function(err, foundItem) {
if (err || !foundItem) {
console.log(err);
} else {
res.locals.translationServiceData = foundItem;
}
});
Language.find({}, function(err, foundItem) {
if (err || !foundItem) {
console.log(err);
} else {
res.locals.languageData = foundItem;
}
});
next();
});
一旦我这样做,我就会得到一个错误。但是,如果我多次重新加载页面,则有时会呈现视图。我想如果发生错误,则会在从数据库检索res.locals之前呈现视图。
ReferenceError: /Users/.../views/contact.ejs:5
3|
4| <% include partials/head %>
>> 5| <% include partials/header %>
6|
7| <!-- Page Title
8| ============================================= -->
/Users/.../views/partials/header.ejs:21
19| ============================================= -->
20|
>> 21| <% include ../partials/navbar %>
22|
23| <!-- #primary-menu end -->
24| </div>
/Users/.../views/partials/navbar.ejs:5
3| <li><a href="/translation-services"><div class="on-click">Translation</div></a>
4| <ul>
>> 5| <% translationServiceData.sort((a, b) => a.slug.localeCompare(b.slug)); %>
6| <% translationServiceData.forEach(function(item){ %>
7| <li><a href="/translation-services/<%= item.slug %>"><div class="on-click"><%= item.slug %> translation</div></a></li>
8| <% }); %>
translationServiceData is not defined
我认为这与节点js异步加载有关,但是我不确定,我也不知道如何解决此问题。也许使用res.locals来构建导航栏是一个过大的杀伤力,必须采取另一种方式。任何帮助表示赞赏。
答案 0 :(得分:0)
原因是您在从数据库获取任何数据之前正在调用next()。
app.use(function(req,res,next){
res.locals.currentUser = req.user;
res.locals.success = req.flash('success');
res.locals.error = req.flash('error');
TranslationService.find({}, function(err, foundItem) {
if (err || !foundItem) {
console.log(err);
} else {
res.locals.translationServiceData = foundItem;
}
});
Language.find({}, function(err, foundItem) {
if (err || !foundItem) {
console.log(err);
} else {
res.locals.languageData = foundItem;
}
});
//res.locals.translationServiceData and res.locals.languageData
//are still undefined because the above db calls haven't returned any data yet
//since the db calls are asynchronous
next();
});
最简单的解决方案是这个
app.use(function(req,res,next){
res.locals.currentUser = req.user;
res.locals.success = req.flash('success');
res.locals.error = req.flash('error');
TranslationService.find({}, function(err, foundItem) {
if (err || !foundItem) {
console.log(err);
} else {
res.locals.translationServiceData = foundItem;
}
Language.find({}, function(err, foundItem) {
if (err || !foundItem) {
console.log(err);
} else {
res.locals.languageData = foundItem;
}
// call next once you have all the data
next();
});
});
});