I am learning sqlite3
in Node.js and having problem with following code
var sqlite3 = require('sqlite3').verbose();
var db = new sqlite3.Database('first.db');
console.log("in the program");
var x = [];
console.log("x = ", x);
console.log("db.all()");
db.all("SELECT * FROM coords",
function(err, rows) {
console.log("\nin db.all()");
for(var row of rows) {
x.push(row.x);
console.log(x);
}
}
);
db.close();
console.log("x = ", x);
where the output is
> node dball.js
in the program
x = []
db.all()
x = []
in db.all()
[ 1 ]
[ 1, 5 ]
[ 1, 5, 9 ]
It seems that all lines outside db.all()
are executed first than the others inside it, so that array of x
seems not changed, since it is printed before it is updated.
Is there any way force all lines are executed in serial instead sort of concurrent? I believe I am missing the concept of concurrency here but not know how to do.
Thank's for any help.
db.all
is a function that takes 2 inputs: the query as a string and a callback function which will be called later when the database managed to run the query and have the results (or an error) ready to report back to you. I suggest you read more about the nature of asynchronous code in JavaScript: callbacks, promises, async/await, etc. Also, we no longer use var
to declare variables.
That being said, what you can actually do is to "promisify" db.all
function and then use async/await
to make it look synchronous (it will still be async code).
const sqlite3 = require('sqlite3').verbose();
const db = new sqlite3.Database('first.db');
function getData(query) {
// promisifying
return new Promise((resolve, reject) => {
db.all(query, (err, rows) => {
if (err) {
reject(err);
return;
}
resolve(rows);
}); // db.all
}); // new Promise
} // getData
// main is needed because some JS engines don't allow top level "await"
// so I am playing safe here
async function main() {
console.log("in the program");
const x = [];
console.log("x = ", x);
console.log("db.all()");
try {
// the nice thing is that you don't even need `x` now because
// you can just do something with `rows`
const rows = await getData("SELECT * FROM coords");
for(var row of rows) {
x.push(row.x);
console.log(x);
}
} catch (err) {
// do something in case of error
} finally {
// this is always executed regardless of error or not
// so it is a good place to close the database
db.close();
}
console.log("x = ", x);
}
// make sure to call main
main();