So basically I have two js-scripts; one is router, made with node and express:
import express from "express";
import showContent from "../model/model.js";
const router = express.Router();
//* Sends out the ejs (basically HTML) on start URL "localhost:8080"
router.get("/", function (req, res) {
res.render("../pages/start.ejs");
});
//* Querys the database, the table ":id"
router.get("/:id", function (req, res, next) {
id = req.params.id;
let sqlQuery = `SELECT page_content FROM ${id} WHERE page_name = "about";`;
console.log("1", showContent(sqlQuery));
res.send(showContent(sqlQuery));
next();
});
export default router;
and the other is a script with an async function fetching data from my SQLite db:
import sqlite3 from "sqlite3";
const db = new sqlite3.Database(
"path/to/my/db"
);
export default function getContent(sqlQuery, whenloaded) {
return new Promise((resolve) => {
resolve(
db.all(sqlQuery, [], (err, rows) => {
if (err) {
console.error(err);
} else {
rows.forEach((row) => {
whenloaded(row.page_content);
});
}
})
);
});
}
async function showContent(sqlQuery) {
await getContent(sqlQuery, (result) => {
console.log("Result:", result);
});
}
The output in my browser is {}
and the console logs I get are:
1 Promise { <pending> }
, Result: "my content"
and Result "my content"
.
I think the problem is that I genuinely don´t understand async functions, and I don´t know how to use them in my code.
CodePudding user response:
There are 3 problems with your code.
The first one, is that you are not waiting on the async function showContent
to complete. That is why you receive the message of a pending Promise. I advise you to read up on Promises to understand async Javascript code better. In short: Promises are the underlying vehicle upon which async functionality is built.
To fix this problem, update your router code to wait for the showContent function before sending back the response:
router.get("/:id", async function (req, res, next) {
const id = req.params.id;
const sqlQuery = `SELECT page_content FROM ${id} WHERE page_name = "about";`;
const content = await showContent(sqlQuery);
console.log("1", content);
res.send(content);
next();
});
The second problem is that you are exporting a default
function and a showContent
function from your model file. However, you use the import statement:
import showContent from "../model/model.js";
Which imports the default export of the model.js file, in your case the getContent
function, and assigns it to the local variable showContent
. My assumption is that you actually wanted the showContent
function, so you should update the import statement to (notice the curly braces):
import { showContent } from "../model/model.js";
The third problem is with the async code in your model file. Firstly, the showContent
function does not return anything. Hence, waiting for the result will yield undefined
. Secondly, you should restructure the getContent
function so you do not need the whenLoaded
callback by employing the power of Promises correctly. Update the model code to:
import sqlite3 from "sqlite3";
const db = new sqlite3.Database(
"path/to/my/db"
);
export function showContent(sqlQuery) {
return new Promise((resolve, reject) => {
db.all(sqlQuery, [], (err, rows) => {
if (err) {
reject(err);
} else {
resolve(rows);
}
});
});
}
I've removed the now redundant showContent function and renamed the getContent function to showContent so your previously updated import statement still works. You can of course always update the naming and reintroduce the default export (but remember to remove the curly braces from the import statement if you do).