SQLite3 and NodeJS / Electron : Asynchronism issue

37 Views Asked by At

I am working on an Electron app which uses a SQLite database.

It works fine, except one thing I have been struggling with since the beginning : if the local database doesn't exist, the program creates it with all the tables so the user starts with a new database. However, the function that creates the database doesn't wait for the sqlite3 constructor to finish, so the program starts querying the tables although they are not created yet. I have to restart the app after the db is created in order to start using the program.

If the database already exists, there is no problem at all (which I don't understand, as the same constructor is used in both cases... maybe it is fast enough to finish before the other instructions are executed when the database doesn't have to be created?).

You can find the relevant code below. I've added some console.log() to see in which order the code is executed (result at the end).

main.js:

const { app, BrowserWindow, ipcMain } = require('electron');

const path = require('path');
const ejse = require('ejs-electron');
const { shell } = require('electron');

const db = require('./models/db');

const color_model = require('./models/color');
const board_model = require('./models/board');
const list_model = require('./models/list');
const task_model = require('./models/task');
const tag_model = require('./models/tag');
const tasktag_model = require('./models/tasktag');

var win;

const { marked } = require('marked');

const months = ["January","February","March","April","May","June", 
                "July","August","September","October","November","December"];


const createWindow = async function() {

    await load_board_list();
    await load_colors();

    //...

    win.loadFile('./src/components/index.ejs');
    win.maximize();
}

app.whenReady().then(async () => {
    createWindow();
    // ...
});

async function load_board_list() {
    await board_model.readall_unarchived().then(function(result) {
        ejse.data('boards', result);
    }).catch(function(err) { throw err; });
}

async function load_colors() {
    await color_model.readall().then(function(result) {
        ejse.data('colors', result);
    }).catch(function(err) { throw err; });
}

// ...

db.js:

const sqlite = require('sqlite3').verbose();
const fs = require('fs');

var dbPath = getConfig();

var db = new sqlite.Database(dbPath, sqlite.OPEN_READWRITE, async (err) => {
    if (err && err.code == "SQLITE_CANTOPEN") {
        console.log("getDB(): The database doesn't exist, let's create it.");
        console.log("===== schtroumpf 1")
        await createDatabase();
        console.log("===== schtroumpf 5")
    } else if (err) {
        console.log("getDB(): Getting error: " + err);
    }
});

function getConfig() {
        // ...
}

async function createDatabase() {
    console.log("===== schtroumpf 2.1")
    db = new sqlite.Database(dbPath, async (err) => {
        console.log("===== schtroumpf 2.2")
        if (err) {
            console.log("createDatabase(): Getting error: " + err);
        }
        console.log("===== schtroumpf 2.3")
        await createTables(db);
        console.log("===== schtroumpf 4")
    });
}

async function createTables(newdb) {
        // ...
}

board.js:

var db = require('./db.js');
var list_model = require('./list.js')

module.exports = {

    // ...

    readall_unarchived: function() {
        return new Promise(function(resolve, reject) {
            console.log("\n[Board] Readall_unarchived()");

            let query = "SELECT * FROM Board "+
                        "WHERE archived = 0 "+
                        "ORDER BY name COLLATE NOCASE ASC ;";

            db.all(query, function (err, rows) {
                if (err) { return reject(err) }
                resolve(rows);
            });
        });
    },

    // ...
}

When I launch the program with no available database, these lines are being written in the terminal:

> [email protected] start
> electron .

Database path: ./db/milvago.db
getDB(): The database doesn't exist, let's create it.
===== schtroumpf 1
===== schtroumpf 2.1        
===== schtroumpf 5                     

[Board] Readall_unarchived()
===== schtroumpf 2.2
===== schtroumpf 2.3
===== schtroumpf 3.1                   
===== schtroumpf 3.2
===== schtroumpf 3.3
===== schtroumpf 4

Here, we can see that the program tries to execute a query to read the unarchived boards before the tables are created (prints 3.1 to 4). This leads the program to be blocked, I don't have any error (which I don't understand why). I guess the const db = require('./models/db'); doesn't get the value of the database updated after it has been completely created. Maybe the program is waiting for it to be ready, which never happens and that's why I don't have any error?

Would be possible to force the program to wait for the constructor to finish?

I have been looking for a solution for hours but I haven't found anything that is reliable ; my skills with javascript are still limited so there may be something I haven't understood yet about the way it works.

I have tried a lot of things:

  • promises
  • flags that would tell when the database is ready
  • completely changing the structure of the db.js file to call each function from main.js
  • and other things I have forgotten as I started working on my app in august (with a 2 months break after that)

But nothing worked.

0

There are 0 best solutions below