[英]Execute Sequelize queries synchronously
我正在使用 Node.js 和 Sequelize(带有 Postgres 后端)构建一个网站。 我有一个查询,它返回许多带有外键的对象,我想将外键引用的对象列表传递给视图。
在示例中,Attendances 包含 Hackathon 密钥,我想返回一个黑客马拉松列表。 由于代码是异步的,下面的事情当然在 Node 中不起作用:
models.Attendance.findAll({
where: {
UserId: req.user.id
}
}).then(function (data) {
var hacks = [];
for (var d in data) {
models.Hackathon.findOne({
where: {
id: data[d].id
}
}).then(function (data1) {
hacks.append(data1);
});
}
res.render('dashboard/index.ejs', {title: 'My Hackathons', user: req.user, hacks: hacks});
});
有没有办法以同步方式执行该查询,这意味着在我将“hacks”列表填满所有对象之前,我不会返回视图?
谢谢!
使用Promise.all
执行所有查询,然后调用下一个函数。
models.Attendance.findAll({ where: { UserId: req.user.id } }).then(function (data) { // get an array of the data keys, (not sure if you need to do this) // it is unclear whether data is an object of users or an array. I assume // it's an object as you used a `for in` loop const keys = Object.keys(data) // map the data keys to [Promise(query), Promise(query), {...}] const hacks = keys.map((d) => { return models.Hackathon.findOne({ where: { id: data[d].id } }) }) // user Promise.all to resolve all of the promises asynchronously Promise.all(hacks) // this will be called once all promises have resolved so // you can modify your data. it will be an array of the returned values .then((users) => { const [user1, user2, {...}] = users res.render('dashboard/index.ejs', { title: 'My Hackathons', user: req.user, hacks: users }); }) });
Sequelize 库具有包含参数,可在一次调用中合并模型。 调整您的 where 语句,将Hackathons模型引入到考勤中。 如果这不起作用,请花必要的时间正确设置 Sequelize,他们的文档正在不断改进。 最后,您将通过减少错误并使您的代码对其他程序员可读来节省大量时间。
看看这能干净到什么程度……
models.Attendance.findAll({
include: [{
model: Hackathon,
as: 'hackathon'
},
where: {
UserId: req.user.id
}
}).then(function (data) {
// hackathon id
console.log(data.hackathon.id)
// attendance id
console.log(data.id)
})
还有..
Hackathon.belongsTo(Attendance)
Attendance.hasMany(Hackathon)
sequelize.sync().then(() => {
// this is where we continue ...
})
在此处了解有关 Sequelize 的更多信息: http ://docs.sequelizejs.com/en/latest/docs/models-usage/
立即调用异步函数表达式
这是在以下内容中提到的技术之一: 如何在顶层使用 async/await? 顶层 await 可能会在 2021 年即将到来,这会更好。
最小可运行示例:
const assert = require('assert');
const { Sequelize, DataTypes } = require('sequelize');
const sequelize = new Sequelize({
dialect: 'sqlite',
storage: 'db.sqlite',
});
const IntegerNames = sequelize.define(
'IntegerNames', {
value: { type: DataTypes.INTEGER, allowNull: false },
name: { type: DataTypes.STRING, },
}, {});
(async () => {
await IntegerNames.sync({force: true})
await IntegerNames.create({value: 2, name: 'two'});
await IntegerNames.create({value: 3, name: 'three'});
await IntegerNames.create({value: 5, name: 'five'});
// Fill array.
let integerNames = [];
integerNames.push(await IntegerNames.findOne({
where: {value: 2}
}));
integerNames.push(await IntegerNames.findOne({
where: {value: 3}
}));
// Use array.
assert(integerNames[0].name === 'two');
assert(integerNames[1].name === 'three');
await sequelize.close();
})();
在 Node v14.16.0、sequelize 6.6.2、seqlite3 5.0.2、Ubuntu 20.10 上测试。
在异步函数中使用for of
models.Attendance.findAll({
where: {
UserId: req.user.id
}
}).then(async (data) => {
let hacks = []
for (const d of data) {
const _hack = await models.Hackathon.findOne({
where: {
id: data[d].id
}
})
hacks = [...hacks, _hack]
}
res.render('dashboard/index.ejs', {title: 'My Hackathons', user: req.user, hacks: hacks})
})
这将在渲染之前等待 hacks 数组被填满。 这应该适用于 API 端点。
希望这会帮助任何遇到同样问题的人。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.