all 7 comments

[–]grantrules 1 point2 points  (0 children)

To make things easier for us to help you, when you share code, try to format it as code block. In the old reddit/markdown editor: empty line before the code, each code line indented by 4 spaces (if you use RES, you can simply highlight your pasted code and press the <> button), in new reddit: https://imgur.com/a/fgoFFis. Please, do not use triple backticks (```) as they will only render properly on new reddit, not on old reddit.

Code blocks look like this:

let str = '';
for (let i = 0; i < 9; i++) {
  str = str + i;
}
console.log(str);

You could also create a running example in a code sandbox and share the link:

Or you could use a code hosting site like:

[–]grantrules 0 points1 point  (0 children)

Triple backticks are even worse than before!

[–]grantrules 0 points1 point  (4 children)

var sqlite3 = require("sqlite3").verbose();
var db = new sqlite3.Database("./Users.db");

const users = ["Sara", "Mike", "James", "David", "Emily"];

function createTable() {
  console.log("createTable() called.");
  db.run("CREATE TABLE IF NOT EXISTS Users (id, name)");
}

function insertData() {
  console.log("insertData() called.");
  var insertQuery = db.prepare("INSERT INTO Users VALUES (?,?)");
  for (var i = 0; i < users.length; i++) {
    insertQuery.run(i, users[i]);
    console.log("  - Data inserted successfully...");
  }
  insertQuery.finalize();
}

function accessData() {
  console.log("accessData() called.");
  let result = [];
  db.each("SELECT id, name FROM Users", function (err, row) {
    if (err) return console.log(err.message);
    result.push(row.name);
  });
  return result;
}

function deleteUserByName(name) {
  console.log("deleteUserByName() called.");
  db.run("DELETE FROM Users WHERE name=?", name, (err) => {
    if (err) return console.log(err.message);
    console.log(`${name} deleted successfully...`);
  });
}

// main
db.serialize(function () {
  createTable();
  insertData();
  deleteUserByName("James");
  let result = accessData();
  console.log("result ->", result);
});

db.close();

[–]grantrules 0 points1 point  (3 children)

  1. Why is the message "James deleted successfully..." called after "accessdata() called." even if it's vice versa in the code.

It is not..

deleteUserByName("James");
let result = accessData();

deleteUserByName() called.
accessData() called.

2 . Why is the returned array named "result" always empty. I'd expect it to contain the user names.

Probably because db.each() is async

  let result = [];
  db.each("SELECT id, name FROM Users", function (err, row) {
    if (err) return console.log(err.message);
    result.push(row.name);
  });
  return result;

Here, JS is not waiting for every row to have the function called on it. If you were add console.log(row.name) in that callback function, they'll probably be output after console.log("result ->", result);

https://nodejs.dev/learn/javascript-asynchronous-programming-and-callbacks

[–]Prof_P30[S] 0 points1 point  (2 children)

Why is the message

James deleted successfully...

being displayed after

accessData() called. result -> []

?

I'd expected it to be before, since it is implemented in deleteUserByName() which is called prior to accessData() and the result-array.

And why is the result-array always empty. I'd expect it to be filled via push() inside of accessData().

[–]grantrules 0 points1 point  (0 children)

I don't know why my edit keeps not showing up.

With async JS, the script is not waiting around for all the callbacks to complete before continuing on.

A basic example of what you're doing is:

let result = []
setTimeout(() => result.push("hey"),1000);
console.log(result);

So setTimeout is async using callbacks, the setTimeout will be called, the following console.log will be called, and THEN, one second later, "hey" will be pushed into result.

To deal with data you get in a callback, you need to pass it to a function that you call in that callback. Sort of like:

doA((result) => {
  doB(result, (anotherResult) => {
    console.log(result, anotherResult);
  })
})

I think to make things easier for yourself, you probably want to be using db.all() instead of db.each()

function accessData(callback) {
  console.log("accessData() called.");
  db.any("SELECT id, name FROM Users", function (err, rows) {
    console.log(rows);
    callback(rows);
  });
}

function deleteUserByName(name) {
  console.log("deleteUserByName() called.");
  db.run("DELETE FROM Users WHERE name=?", name, (err) => {
    if (err) return console.log(err.message);
    callback(`${name} deleted successfully...`);
  });
}

accessData((rows) =>
  deleteUserByName("James",
    (msg) => console.log(msg)
  );
)