0

In the below code, users.push used within ‘db.each’ wont work. However, if I move ‘users.push’ outside then it seems to work.

How can I push the new objects from db.each into the users array?

let db = new sqlite3.Database('./db/main.db', (err) => {
  if (err) console.error(err.message);
  console.log('Connected to the main database.');
});

var users = [];

db.serialize(() => {
  db.each(`SELECT email, name FROM users`, (err, row) => {
    if (err) console.error(err.message);
    let user = {
      email: row.email,
      name: row.name
    }
    users.push(user);
  });
});

console.log(JSON.stringify(users));
db.close();

I am using express and sqlite3 node packages.

Nino Filiu
  • 16,660
  • 11
  • 54
  • 84
esafwan
  • 17,311
  • 33
  • 107
  • 166
  • 1
    looks like you are pushing users inside callback, so it happens later then you try to output array to console. Does sqlite3 support promises? Code will be much more clear with async/await then – Yuri Gor Mar 11 '19 at 19:50
  • @YuriGor Thanks for the pointer. It never crossed my mind. I saw question precisely around this. https://stackoverflow.com/questions/46994203/sqlite3-promise-for-asynchronous-calls – esafwan Mar 11 '19 at 20:00
  • Possible duplicate of [How do I return the response from an asynchronous call?](https://stackoverflow.com/q/14220321/218196) and [Why is my variable unaltered after I modify it inside of a function? - Asynchronous code reference](https://stackoverflow.com/q/23667086/218196). – Felix Kling Mar 11 '19 at 20:02

2 Answers2

2

It's because db.serializeand db.each are asynchronous functions (and return immediately, thus executing console.log before the db callbacks are executed).

Here should be a working example :

db.serialize(() => {
      db.each(`SELECT email,
                      name
               FROM users`, (err, row) => {
        if (err) {
          console.error(err.message);
        }

        let user = {
            email : row.email,
            name : row.name
        }

        users.push(user);

        console.log(JSON.stringify(users));

        db.close(); 

      });
    });
1

First error: asynchronicity not handled properly

As Antoine Chalifour pointed out, you call console.log(JSON.stringify(users)); before users gets modified in the asynchronous callback. Refer to his answer for fix and explanations.

Second error: errors not handled

You wrote if (err) { console.error(err.message); } then go on with the rest of the function. That is bad, because an error might happen and you'd just continue with your program. You should instead write something like:

if (err) {
  console.error(err);
  return;
}

or:

if (err) throw err;
Nino Filiu
  • 16,660
  • 11
  • 54
  • 84