我试图先在循环内使用Knex在MySQL中插入数据,然后再获取数据。但是,获取数据首先在插入之前执行。 有人可以帮我吗?
for (let i = 0; i < fileArray.length; i++) {
fileLocation = fileArray[i].location;
imgLocationArray.push(fileLocation);
knex("files")
.insert({
fileLink: fileLocation,
todoId: todoId,
userId: userId
})
.then(() => {
console.log("phle chala!");
})
.catch(err => console.log(err));
}
knex("files")
.where("files.userId", userId)
.then(userFiles => {
console.log("baad wala hai yrr");
res.json({
userFiles: userFiles
});
})
.catch(err => console.log(err));
答案 0 :(得分:1)
使用诺言时(如Knex查询所做的那样),JavaScript将直接继续到下一条语句,而无需等待前一条语句完成。这就是您在这里遇到的:您的代码启动所有数据库插入,但是在发出查询以取回数据之前,不等待它们完成。
由于您要遍历一系列文件,Promise.all
是解决方案的理想选择。运作方式如下。首先,我们兑现了所有承诺:
const insertions = fileArray.map(file => {
fileLocation = fileArray[i].location;
imgLocationArray.push(fileLocation);
return knex("files")
.insert({
fileLink: fileLocation,
todoId: todoId,
userId: userId
})
})
请注意此处的return
语句,这非常重要。接下来,我们等待等待所有这些诺言完成:
Promise.all(insertions)
.then(() => knex("files").where("files.userId", userId))
.then(userFiles => {
console.log("baad wala hai yrr");
res.json({
userFiles: userFiles
});
})
.catch(err => console.log(err));
只有在最后一个.then
块中,我们才能依赖于可用数据,因为所有先前的查询都已完成。
如果您恰巧在服务器上有async
/ await
可用的环境中(7.6之后的节点版本),则可以执行以下操作:
try {
await Promise.all(insertions);
const userFiles = await knex("files").where("files.userId", userId);
res.json({ userFiles });
} catch (e) {
// Handle database error
}
许多人发现此语法更具可读性。请注意,包含此代码的函数必须使用async
关键字声明:
myExpressRouter.post("userfiles", async (req, res) => {
// ...
})