Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Asynchronous initialization of express.js (or similar) apps

Consider an example: I have the following express.js app (see code snippet below). I want to have one persistent connection to the DB, and one persistent connection to my own service (which required async call to start) during entire app lifetime. And there are a few entry points, i.e. one can access my app not only via HTTP protocol. Of course, I want to avoid service initialization code duplication and there could be several such async-initializing services.

/* app.js */
var app = require('express')();
// set views, use routes, etc.
var db = require('monk/mongoose/etc')(...); // happily, usually it's a sync operation
var myService = require('./myService');     // however, it's possible to have several such services
myService.init(function(err, result) {
    // only here an initialization process is finished!
});

module.exports.app = app;


/* http_server.js (www entry point) */
var app = require('app');
// create an HTTP server with this app and start listening


/* telnet_server.js (other entry point) */
var app = require('app');
// create a Telnet server with this app and start listening

In the code snippet above, by the time http (or telnet, or any other) server is starting, there is no guarantee, that myService already has initialized.

So, I have to somehow reorganize my app creation code. For now I stick with the next solution:

/* app.js */
var app = require('express')();
module.exports.app = app;
module.exports.init = function(callback) {
    var myService = require('./myService');
    myService.init(callback);     
}

/* entry_point.js */
var app = require('app');
app.init(function(err) {
    if (!err) {
        // create an HTTP/Telnet/etc server and start listening
    }
});

So, my question is: what is the common way to initialize services required asynchronous call to start?

like image 956
Ivan Velichko Avatar asked Jan 07 '16 16:01

Ivan Velichko


1 Answers

I would recommend you to promisify the initialization function of your services(s) and then use them in the following manner:

const app = require('express')();
const util = require('util');
const myService = require('./myService');
const myServiceInit = util.promisify(myService.init);
Promise.all([myServiceInit]).then(() => {
  // delayed listening of your app
  app.listen(2000);
}).catch(err => {
 // handle error here
});

I've used Promise.all in order for you to add initialization of multiple internal services.

The pre-requisite of promisifying your init function is that it should be using an error first callback mechanism. You can read more about it here Node Official Doc

Hope this helps your cause.

like image 145
Aashish Ailawadi Avatar answered Nov 17 '22 17:11

Aashish Ailawadi