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


consider example: have following express.js app (see code snippet below). want have 1 persistent connection db, , 1 persistent connection own service (which required async call start) during entire app lifetime. , there few entry points, i.e. 1 can access app not via http protocol. of course, want avoid service initialization code duplication , there several such async-initializing services.

/* app.js */ var app = require('express')(); // set views, use routes, etc. var db = require('monk/mongoose/etc')(...); // happily, it's sync operation var myservice = require('./myservice');     // however, it's possible have several such services myservice.init(function(err, result) {     // here initialization process finished! });  module.exports.app = app;   /* http_server.js (www entry point) */ var app = require('app'); // create http server app , start listening   /* telnet_server.js (other entry point) */ var app = require('app'); // create telnet server app , start listening 

in code snippet above, time http (or telnet, or other) server starting, there no guarantee, myservice has initialized.

so, have somehow reorganize app creation code. stick 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 http/telnet/etc server , start listening     } }); 

so, question is: common way initialize services required asynchronous call start?

i've created gist here sample of code use task. (it uses q promise library, modified use other promises lib).

the basic idea describe app backbone sequence of asynchronous initialization steps. each step calls 1 or more async functions , binds result name; startup process progresses next initialization step once values resolved current step, , subsequent steps can access values resolved previous steps. allows dependency order of services , components within app described.

for example, backbone can defined follows:

var app = [   { s1: startservice1 },   { s2: startservice2, s3: startservice3 },   { s4: startservice4 } ] 

(note in each step definition, references each function given; start() function - shown in gist - invoke each function in correct order).

each of startxxx vars function takes single argument, , returns deferred promise, e.g.:

function startservice4( app ) {     var s1 = app.s1;     var s2 = app.s2;     var deferred = q.defer();     // ... start service, async stuff ...     return deferred; } 

the function's app argument represents configured app backbone, , results previous initialization steps available named properties.

i've used pattern in complicated systems, , find simple, flexible , effective way define system's high level structure.


Comments

Popular posts from this blog

ruby - Trying to change last to "x"s to 23 -

jquery - Clone last and append item to closest class -

c - Unrecognised emulation mode: elf_i386 on MinGW32 -