我有一个基于NodeJS,Express和Jade 4.13.4的Web应用程序。在index.js
我设置了如下路线:
index.js
var express = require('express')
, app = express()
, companyroutes = require('./routes/company')
(...)
app.use('/company/', companyroutes)
路由/ company.js
var express = require('express')
, router = express.Router()
router.all('/:id*', function(req, res, next) {
res.locals.companyUri = '/company/' + req.params.id;
async.parallel([
// company data
function(done){
api.getCompany(req.params.id, req.user, done)
},
// user follows data
function(done){
api.follows(req.params.id, req.user, 'company', done))
}
],
function(err, result){
if (err){
return next(err)
}
res.locals.company = result[0]
res.locals.userFollows = result[1]
company.getCompanyOverview(res.locals.company, function(err, results){
if (err) {
return next(err)
}
debug('render company overview')
res.render('company-overview', results)
})
})
});
module.exports = router;
正如您所看到的,我有一条路由用作中间件,执行以下操作:
res.locals
和company
来丰富userFollows
company.getCompanyOverview
,使用async.parallel
包含对API的更多调用。收到的数据存储在results
。company-overview
渲染玉视图results
。到目前为止一切顺利。当对http://localhost:3000/company/companyA
进行一次调用时,会从API中获取所有数据,并通过呈现模板正确显示companyA
的数据。
但是,对于并发请求,行为是不同的。我在OSX下使用ApacheBench通过请求另一家公司来对服务器施加一些负担:
brew install parallel
echo /company/companyB | parallel 'ab -c 10 -n 5000 http://localhost:3000{}'
使用浏览器访问网站http://localhost:3000/company/companyA
时,会显示companyB
的基本数据,而不是companyA
。
Express Docs明确指出res.locals
的范围限定为单个请求的生命周期:
包含作用域的响应局部变量的对象 请求,因此仅适用于在期间呈现的视图 请求/响应周期(如果有的话)。
但是对我而言,似乎res.locals
被ApacheBench的请求覆盖了。从另一台机器运行AB时也是如此!
我已经在这方面投入了太多时间,但我仍然没有得到它。这是Express中的错误还是我做错了什么?
使用的版本
$ node -v
v4.2.2
$ npm list express
moneyhouse@1.1.1-dev.2 /Users/dani/Documents/mh-web
├─┬ browser-sync@2.13.0
│ └─┬ browser-sync-ui@0.6.0
│ └─┬ weinre@2.0.0-pre-I0Z7U9OV
│ └── express@2.5.11
└── express@4.13.4
$ npm list jade
moneyhouse@1.1.1-dev.2 /Users/dani/Documents/mh-web
├── jade@1.11.0
└─┬ jade-glob-include@1.0.1
└── jade@1.3.1
答案 0 :(得分:1)
我遇到了同样的错误。最终看起来它是由我首先设置res.local的原因引起的。 我有一个简单的=运算符
res.local.VALUE = req.VALUE.
' ='不会像您期望的那样分配变量,而是仅引用req.VALUE,这意味着当并发请求进入并且req.VALUE更新时,该值可能会被交换。
我通过克隆对象来解决这个问题:
res.local.VALUE = _.clone(req.VALUE) //using underscore
所以res.local.VALUE不再依赖于req,而是它自己的对象。