Ich habe eine Webanwendung basierend auf NodeJS, Express und Jade 4.13.4.NodeJS/Express: Concurrency-Problem beim Zugriff auf res.locals
index.js
var express = require('express')
, app = express()
, companyroutes = require('./routes/company')
(...)
app.use('/company/', companyroutes)
Routen/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;
Wie Sie sehen können, habe ich eine einzige: In index.js
Ich habe eine Route wie folgt aufgebaut Route, die als Middleware verwendet wird, die folgende Schritte ausführt:
- bereichern
res.locals
mit einigen allgemeinen Unternehmensdaten (company
unduserFollows
aus zwei asynchronen, parallelen Anrufen an eine API erhalten) - weiteren Anruf zu
company.getCompanyOverview
macht, die ein paar mehr Anrufe an den APIasync.parallel
einwickelt. Die empfangenen Daten werden inresults
gespeichert. - Rendern Sie die Jade Ansicht
company-overview
mitresults
.
So weit so gut. Bei einem einzelnen Aufruf an http://localhost:3000/company/companyA
ruft alle Daten von der API und zeigt die Daten für companyA
korrekt durch Rendern der Vorlage.
Bei gleichzeitigen Anforderungen unterscheidet sich das Verhalten jedoch. Ich benutze Apachebench unter OSX einige Lasten auf dem Server zu setzen, indem eine andere Firma anfordernden:
brew install parallel
echo /company/companyB | parallel 'ab -c 10 -n 5000 http://localhost:3000{}'
Wenn die Website http://localhost:3000/company/companyA
mit einem Browser zugreift, werden die Basisdaten für companyB
statt companyA
gezeigt.
Die Express Docs klar sagen, dass res.locals
auf den Lebenszyklus einer einzigen Anfrage scoped ist:
Ein Objekt, das Antwort lokale Variablen scoped auf die Anforderung enthält und daher nur zur Ansicht (n) gemacht während dieser Anfrage/Antwort-Zyklus (falls vorhanden).
Für mich sieht es jedoch wie res.locals
wird durch die Anforderungen von ApacheBench überschrieben. Dies ist auch der Fall, wenn AB von einer anderen Maschine läuft!
Ich habe schon viel zu viel Zeit in dieses investiert und ich verstehe es immer noch nicht. Ist es ein Fehler in Express oder mache ich etwas falsch?
Versionen verwendet
$ node -v
v4.2.2
$ npm list express
[email protected] /Users/dani/Documents/mh-web
├─┬ [email protected]
│ └─┬ [email protected]
│ └─┬ [email protected]
│ └── [email protected]
└── [email protected]
$ npm list jade
[email protected] /Users/dani/Documents/mh-web
├── [email protected]
└─┬ [email protected]
└── [email protected]
Probieren Sie 'req' und' page-result' aus, um für jede Anfrage A und B wie z.B. 'console.log (req.params.id, result [0], result [1], req.app.render ('Firmenübersicht', results))'. Wenn gedruckte Daten korrekt sind, dann kann es Probleme im Browser-Cache geben, sonst können Sie sehen, wo das Problem beginnt. –
Dies wird fast immer von einer Variablen verursacht, die Sie nicht deklariert haben, was sie zu einer globalen Variable macht (die bei jeder Anfrage überschrieben wird). Dies ist kein Fehler in Express. – robertklep