Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Running an async function before express.js start

I want to run an async operation (for example, wait for a URL call to complete) before I start my app. I don't know how to do that (since it's an upper-level application - no async/await here).

www.js:

var app = require('./app');
var http = require('http');
const port = '3000';
app.set('port', port);
var server = http.createServer(app);
server.listen(port);

app.js:

var express = require('express');
var app = express();
var Promise = require('bluebird');

# HERE IS WHERE I WANT TO "AWAIT" AN ASYNCHRONOUS CALL. 
# I KNOW I CAN'T USE AWAIT BECAUSE I'M NOT WITHIN 
# AN "ASYNC" ANNOTATED FUNCTION. EXAMPLE:
const data = await Promise.promisify(fs.readFile('DATA'));

app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
app.use(express.static(path.join(__dirname, 'public')));
app.use('/', routes);
module.exports = app;

I thought about wrapping all of app.js with a Promise.promisify() so I can use async await withing it. But I'm not sure how that would be handled in www.js, since it is not invoked, as in app() but passed on to http.createServer

like image 236
eran Avatar asked Dec 28 '16 14:12

eran


1 Answers

From what you've said, app.js is presumably exporting something (perhaps app?) but that something isn't ready to be used until an asynchronous call (which I don't think you've shown) is complete.

Assuming that's all true, then what app.js exports needs to provide a way for the things using it to wait until it's ready. One way to do that is to use a promise.

Assuming what you're waiting for isn't promise-ified, then:

app.js:

var express = require('express');
var app = express();
exports.appPromise = new Promise(function(resolve, reject) {
    startTheAsyncOperation(function(err, result) {
        if (err) {
            reject(err);
            return;
        }
        app.set('views', path.join(__dirname, 'views'));
        app.set('view engine', 'jade');
        app.use(express.static(path.join(__dirname, 'public')));
        app.use('/', routes);
        resolve(app);
    });
});

then in www.js:

var appPromise = require('./app').appPromise;
var http = require('http');
const port = '3000';
appPromise.then(function(app) {
    app.set('port', port);
    var server = http.createServer(app);
    server.listen(port);
});

Of course, if the async thing you're waiting for provides a promise to you, you don't need new Promise in app.js; instead:

var express = require('express');
var app = express();
exports.appPromise = startTheAsyncOperation().then(function() {
    app.set('views', path.join(__dirname, 'views'));
    app.set('view engine', 'jade');
    app.use(express.static(path.join(__dirname, 'public')));
    app.use('/', routes);
    return app;
});
like image 68
T.J. Crowder Avatar answered Oct 10 '22 03:10

T.J. Crowder