I'm new to Node.js and I'm migrating a simple site of mine to Node.js mostly as a learning experience.
In all my sites, I like to keep the most relevant information on the site in a "sitemeta" object. This is queried from Redis on each request and if that fails (which it only does if sitemeta gets updated and then it reads it from MySQL instead and saves it in redis so that next request again gets it from redis as redis is much speedier than MySQL).
So, in PHP I would simply add the call for sitemeta in a settings.php file that I always include on top of each file so that the information like home_url or site_mode (that are part of sitemeta object) is always there.
However, now in Node.js I was wondering if this is really the way to go or if there's a better way to actually have this happen as a middleware rather than making like so, at the top of every controller file (router files, really).
//in index.js
var express = require('express');
var router = express.Router();
var site = require('./../lib/sitemeta');
...
//using it for something.
var siteMeta = site.meta();
res.render('index', { title: siteMeta.title });
Or, could I even have the sitemeta instantiated in app.js so that it's queried only once (when the node app.js starts) unless it needs to be updated and if so a refresh can be provoked somehow?
Thanks.
I think the best approach is through a middleware. Wherever you store you metadata (memory, redis, etc), having a middleware will let you inject you siteMeta in all requests, with the capacity to adapt your siteMeta based on the received request (locale, etc). We usually use a lot of small, easily testable middleware functions to inject different data elements for another middleware down the pipeline to process and produce the response.
// with promises
app.use(function(req, res, next){
req.siteMeta = loadSiteMeta();
next();
});
app.get('/endpoint', function(req, res){
// wait for the promise to be fulfilled
req.siteMeta.then(function(siteMeta){
res.render('my-view', { title: siteMeta.title });
});
});
// without promises
app.use(function(req, res, next){
loadSiteMeta(function(err, siteMeta){
req.siteMeta = siteMeta;
next();
});
});
app.get('/endpoint', function(req, res) {
// siteMeta will be populated
res.render('my-view', { title: req.siteMeta.title });
});
The actual implementation of loadSiteMeta will depend on your selected storage. The benefits of using promises instead of classic callbacks here is that, if you have multiple middleware loading different data elements before reaching your final processing function, they will be performed in parallel instead of sequentially. You might want to use Promise.all() to wait for all promises you need in your final function.