2

I'm running an express app, in which I want to initialise/open a DB connection before I start listening on a port.

server.js:

const express = require('express');
const morgan = require('morgan');
const db = require('./database/dbUtils');

db.init();
const app = express();
...
app.listen(PORT, () => console.log(`Server running on port ${PORT}.`));

Then, my idea was that I can use that connection in my model to do CRUD operations. For instance, I have a User model that can create a user.

user.js:

const db = require('./database/dbUtils');

async function createUser(user) {
    await db.exec("INSERT INTO users ...");
}

How can I export the connection? I know that exporting is synchronous, so it's impossible to export the DB directly. How do I do that in a conventional way (promise and/or callback)?

dbUtils.js:

const sqlite = require('sqlite3');
const sql = require('sqlite');

async function init() {
    try {
        return await sql.open({
            filename: './database/database.db',
            driver: sqlite.Database 
        });    
    } catch (e) {
        console.error(e);
    }
}

module.exports = init();

Note, in this case, dbUtils.js won't work as it's exporting an async. Even if it worked, it's creating a new connection every time it's imported.

Martin
  • 1,159
  • 10
  • 34

1 Answers1

4

Note, in this case, dbUtils.js won't work as it's exporting an async. Even if it worked, it's creating a new connection every time it's imported.

It shouldn't be.

You're exporting the result of calling this async function, which is going to be a Promise. init() is only getting called once. While you do need to await this everywhere you use it (or use .then()), once a Promise is resolved, future .then or await will resolve immediately to the same value.

In your other files....

const dbPromise = require('./database/dbUtils');

async function createUser(user) {
  const db = await dbPromise;
  await db.exec(...);
}
Brad
  • 159,648
  • 54
  • 349
  • 530
  • I see this is my bad. Yes, this works, but isn't this (exporting a promise) more of a 'trick' than a solid/conventional solution? – Martin May 03 '20 at 18:42
  • @Mitch What's not solid about it? It works fine. The other thing you can do is wait for the database to be set up before continuing to load your app. – Brad May 03 '20 at 19:58
  • I want to avoid exporting a promise. How do I block the app until the db is setup? – Martin May 03 '20 at 20:01
  • 1
    I don't know why you would want to do that, but you really can't, at least not in the way that you're asking. If instead you wanted to simply proxy the whole original module and then await the connection before calling the methods, you could return that proxy immediately. But, don't... this is needless overhead. The other thing you can do is just define some `main()` function that is async, call it, await the DB instance before continuing, as I said in my previous comment. – Brad May 03 '20 at 20:06