Asynchronous initialization of express.js (or similar) apps Asynchronous initialization of express.js (or similar) apps express express

Asynchronous initialization of express.js (or similar) apps


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.


I've created a gist here with a sample of the code I normally use for this task. (It uses the Q promise library, but could easily be modified to use any other promises lib).

The basic idea is to describe the app backbone as a sequence of asynchronous initialization steps. Each step calls one or more async functions and binds the result to a name; the startup process only progresses to the next initialization step once all values are resolved for the current step, and subsequent steps can then access all values resolved by previous steps. This allows the dependency order of services and components within the app to be easily described.

For example, a backbone can be defined as follows:

var app = [  { s1: startService1 },  { s2: startService2, s3: startService3 },  { s4: startService4 }]

(Note that in each step definition, just references to each function are given; the start() function - shown in the gist - will invoke each function in the correct order).

Each of the startXxx vars is a function which takes a single argument, and returns a deferred promise, e.g.:

function startService4( app ) {    var s1 = app.s1;    var s2 = app.s2;    var deferred = Q.defer();    // ... start the service, do async stuff ...    return deferred;}

The function's app argument represents the configured app backbone, and results from previous initialization steps are available as its named properties.

I've used this pattern in fairly complicated systems, and find it a simple, flexible and effective way to define a system's high level structure.