Итак, в основном у меня есть два js-скрипта; один - маршрутизатор, сделанный с узлом и экспрессом:
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.info("1", showContent(sqlQuery));
res.send(showContent(sqlQuery));
next();
});
export default router;
а другой — скрипт с асинхронной функцией, извлекающей данные из моей базы данных SQLite:
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.info("Result:", result);
});
}
Вывод в моем браузере {}
и журналы консоли, которые я получаю:
1 Promise { <pending> }
, Result: "my content"
и Result "my content"
.
Я думаю, проблема в том, что я действительно не понимаю асинхронные функции и не знаю, как использовать их в своем коде.
В вашем коде 3 проблемы.
Во-первых, вы не ждете завершения асинхронной функции showContent
. Вот почему вы получаете сообщение об ожидающем промисе. Я советую вам прочитать промисы, чтобы лучше понять асинхронный код Javascript. Вкратце: промисы — это основное средство, на котором строится асинхронная функциональность.
Чтобы устранить эту проблему, обновите код маршрутизатора, чтобы дождаться функции showContent перед отправкой ответа:
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.info("1", content);
res.send(content);
next();
});
Вторая проблема заключается в том, что вы экспортируете функцию default
и функцию showContent
из файла модели. Однако вы используете оператор импорта:
import showContent from "../model/model.js";
Который импортирует экспорт файла model.js по умолчанию, в вашем случае функцию getContent
, и присваивает его локальной переменной showContent
. Я предполагаю, что вам действительно нужна функция showContent
, поэтому вам следует обновить оператор импорта до (обратите внимание на фигурные скобки):
import { showContent } from "../model/model.js";
Третья проблема связана с асинхронным кодом в вашем файле модели. Во-первых, функция showContent
ничего не возвращает. Следовательно, ожидание результата даст undefined
. Во-вторых, вам следует реструктурировать функцию getContent
, чтобы вам не понадобился обратный вызов whenLoaded
, правильно используя силу промисов. Обновите код модели до:
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);
}
});
});
}
Я удалил теперь избыточную функцию showContent и переименовал функцию getContent в showContent, чтобы ваш ранее обновленный оператор импорта все еще работал. Конечно, вы всегда можете обновить имя и снова ввести экспорт по умолчанию (но не забудьте удалить фигурные скобки из оператора импорта, если вы это сделаете).
Ах да, мой плохой. Это потому, что вы ничего не возвращаете из функции showContent. я обновлю свой ответ
Я как ребенок в рождественское утро, только и ждущий, чтобы открыть мои подарки!
Спасибо вам огромное, огромное!! Вы не представляете, как долго я сидел с этим, пытаясь понять это. Ты герой!!
С удовольствием, рад, что смог быть полезен
Спасибо, звучит вполне разумно, но содержание теперь не определено...?