异步从nodeJS中的sqlite数据库获取数据
Posted
技术标签:
【中文标题】异步从nodeJS中的sqlite数据库获取数据【英文标题】:async get data from sqlite database in nodeJS 【发布时间】:2020-07-14 03:51:09 【问题描述】:这是我的警告命令的代码,它正在从 sqlite 数据库中读取。
user = message.mentions.users.first()
embed = new Discord.MessageEmbed()
.setTitle(`warnings of $user.username`)
.setTimestamp()
.setFooter('shadowcraft - **Test Mode!!**');
sql = 'SELECT * from moderation WHERE userID = ?'
db.each(sql, [user.id], (err, row) =>
if (err) throw err;
mod = client.user.fetch(toString(row.moderatorID))
console.log(row)
embed.addField(`$mod.tag`, `$row.reason \n$row.date`);
);
message.channel.send(embed)
当我运行它时,它会将行打印到控制台,但嵌入是空的并且没有字段。问题是它在从db.each()
获得结果之前发送嵌入
db.each 是回调而不是承诺,所以我不能使用 await
.then()
等
有没有办法将回调变成一个承诺,以便我可以使用异步函数
这是完整的控制台日志,没有错误等,只有行
id: 1,
date: '2020-04-02',
userID: 'some user id',
action: 'WARN',
reason: 'some reason',
moderatorID: 'some user id'
id: 2,
date: '2020-04-02',
userID: 'some user id',
action: 'WARN',
reason: 'some reason',
moderatorID: 'some user id'
【问题讨论】:
你为什么不用WHERE userID = $message.author.id
?它更容易,而且“发件人”必须大写,所以它应该是SELECT * FROM moderation WHERE userID = ?
- 你不必使用?由于用户无法远程更改表中的值,因此您不容易受到 sql 注入的影响
@Proto 这是因为我不想要消息作者,我想要他们提到的用户
啊,尽管如此,请务必大写,道歉
你使用的是什么版本的 Discord.js?
我使用的是 12.1.1
【参考方案1】:
我认为如果你这样做会更干净一些。
将 db.each 更改为 db.all,回调中的行现在将是行
user = message.mentions.users.first()
embed = new Discord.MessageEmbed()
.setTitle(`warnings of $user.username`)
.setTimestamp()
.setFooter('shadowcraft - **Test Mode!!**');
sql = 'SELECT * from moderation WHERE userID = ?'
db.all(sql, [user.id], (err, rows) =>
if (err) throw err;
Promise.all(rows.map((row) =>
return processRow(row)
)).then(result =>
embed.addFields(result);
message.channel.send(embed)
);
);
它还允许您在行集合上完成所有承诺。然后,您将创建一个异步函数并调用该函数以返回一个承诺。这是那个功能。
var processRow = async function(row)
return new Promise((resolve, reject) =>
let mod = client.user.fetch(toString(row.moderatorID))
console.log(row);
resolve(name: mod.tag, value: `$row.reason \n $row.date`);
)
在所有的promise都解决后,它会使用embed.addFields方法,该方法接受一个javascript对象数组,并批量添加字段。在所有处理完成后终于能够发送嵌入。
希望对你有帮助,
【讨论】:
【参考方案2】:看看这个,创建一个新的 Promise 并决定何时解决或拒绝,如果你愿意,你可以默默地拒绝拒绝。
const updateField = db =>
new Promise((resolve, reject) =>
db.each(
'SELECT * from moderation WHERE userID = ?',
(err, row) =>
if (err)
reject(err)
else
mod = client.user.fetch(toString(row.moderatorID))
embed.addField(`$mod.tag`, `$row.reason \n$row.date`)
,
(err, _) =>
if (err)
reject(err)
else
resolve()
)
)
module.exports.main = async () =>
//no idea what your imports/other code looks like...
user = message.mentions.users.first()
embed = new Discord.MessageEmbed()
.setTitle(`warnings of $user.username`)
.setTimestamp()
.setFooter('shadowcraft - **Test Mode!!**')
await updateField(db)
message.channel.send(embed)
【讨论】:
【参考方案3】:Tomi Kordos 几乎得到了正确答案。问题是异步执行。但是,在这种情况下,sqllite 使用回调而不是 promise,因此直接在 db.each 上使用时,await 和 .then 将不起作用。
但是有办法。 Node 提供了一个“promisify”实用程序。这适用于任何最后一个参数是错误优先回调的函数,这正是 db.each 的含义。
您首先需要引入实用程序。
const promisify = require('util');
然后创建对该函数的承诺引用。
const dbeachpr = promisify(db.each);
现在你可以像使用一个 promise 返回函数一样使用这个引用。在这种情况下,我建议将它们存储在一个数组中并使用Promise.all
来确定它们何时完成。
user = message.mentions.users.first()
embed = new Discord.MessageEmbed()
.setTitle(`warnings of $user.username`)
.setTimestamp()
.setFooter('shadowcraft - **Test Mode!!**');
sql = 'SELECT * from moderation WHERE userID = ?'
let promises = [];
promises.push(dbeachpr(sql, [user.id]).then(row =>
mod = client.user.fetch(toString(row.moderatorID))
console.log(row)
embed.addField(`$mod.tag`, `$row.reason \n$row.date`);
).catch(err => throw err); // You may want do something more useful with this.
);
Promise.all(promises).then(() => message.channel.send(embed));
【讨论】:
我收到了错误TypeError: promises.push(...).catch is not a function
@Nodejs-nerd 你之前定义过承诺吗?【参考方案4】:
由于您想获取提到的用户 ID,您可以在 SQL 命令中使用 user.id, 因此,在您的情况下,您需要使用以下 SQL 查询:
`SELECT * from moderation WHERE userID = $user.id`
这样您就可以查询某人的用户 ID 并从中找到所需的警告信息。如果您需要更多解释,请告诉我:)
【讨论】:
【参考方案5】:我不确定,因为我没有使用过 sqlite,但我认为,您正在尝试在实际添加字段之前发送嵌入。 (您正在同步运行该函数)
https://www.npmjs.com/package/sqlite#each
使您的函数异步并使用await db.each
,因此它将等到循环结束,添加所有字段,然后发送嵌入。
或者你可以使用.then()
【讨论】:
我已经尝试过这样做,结果和以前一样,我从 eslint 得到一个错误,说它没有效果以上是关于异步从nodeJS中的sqlite数据库获取数据的主要内容,如果未能解决你的问题,请参考以下文章
从 Nodejs 中的 mySQL 获取数据时如何从 Async/await 函数获取返回值