我目前正在为自己的目的开发一个小型看板应用程序,后端基于打字稿(我是 TS tbh 的新手)和一个简单的 sqlite3 数据库。所以目前我尝试从数据库中获取数据,但这些承诺返回有很多问题。
一张桌子看起来像这样
CREATE TABLE "board" (
"id" INTEGER NOT NULL UNIQUE,
"name" TEXT NOT NULL UNIQUE,
"position" INTEGER NOT NULL UNIQUE,
PRIMARY KEY("id")
)
我的查询只是:
SELECT name FROM board ORDER BY position
所以现在我将该字符串放入我的异步函数中,该函数返回一个承诺,我尝试从董事会标题的函数中获取一个列表 - 看起来像这样:
import { Database } from "sqlite3";
function dbQuery() {
const db = new Database('./data.sqlite3');
return new Promise( resolve => db.serialize(() => {
var result = [];
db.all("SELECT name FROM board ORDER BY position", (err, rows) => {
rows.forEach(function (row) {
//console.log(row['name']);
result.push(row['name']);
});
});
console.log(result);
resolve(result);
})
)
}
async function testFunc() {
let res = await dbQuery();
console.log(res);
}
testFunc();
有人知道为什么最后的数组 res 总是空吗?注释语句console.log(row['name']打印出正确的数据...
对于 SQLITE3 使用纯 JS 可能更好吗? (也许使用更好的sqlite3或类似JS的东西而不是sqlite3和TS?)或者使用其他数据库框架更好?
我像每一个 TS Sqlite3 文档一样用谷歌搜索和阅读,但似乎 TS 和 SQLITE3 并不是那么常见的组合。
您立即(同步)调用
resolve
,而为您提供 rows
的回调会在稍后运行,即异步运行。
也许您认为
serialize
会阻止 JavaScript 继续执行,直到查询结果到来,但事实并非如此:serialize()
将立即返回。 serialize
的目的不是阻止 JavaScript 执行,而是保证 “...一次最多有一个语句对象可以执行查询。”(docs)。您仍然会异步获得结果。在您的情况下,使用 serialize
没有任何优势,因为您只执行一条 SQL 语句。
当执行给
resolve
的回调时,您应该调用 .all()
。所以把它移到那里。
其他一些备注:
.map()
代替 .forEach()
+ .push()
err
参数以查看是否存在错误,在这种情况下,拒绝带有该错误的承诺serialize
包装纸。function dbQuery() {
const db = new Database('./data.sqlite3');
return new Promise((resolve,reject) =>
db.all("SELECT name FROM board ORDER BY position", (err, rows) =>
err ? reject(err)
: resolve(rows.map(row => row['name']))
)
);
}