javascript - Express 服务器在 5 次 GET 请求后停止
问题描述
这段代码的工作方式就像它应该工作一样,但是在第五次GET请求之后,它会在后端执行它应该执行的操作(将数据存储在 db 中),但它没有在服务器上记录任何内容,并且在前端没有任何更改(reactjs)
const express = require('express');
const router = express.Router();
const mongoose = require('mongoose');
const User = require('./login').User;
mongoose.connect('mongodb://localhost:27017/animationsdb');
router.get('/', async(req, res) => {
await User.findOne({ username: req.query.username }, (err, result) => {
if (result) {
// when user goes to his profile we send him the list of animations he liked
// list is stored in array at db, field likedAnimations
res.send({ animationList: result.likedAnimations });
console.log("Lajkovane animacije:", result.likedAnimations);
} else {
console.log("no result found");
res.sendStatus(404)
}
});
});
router.put('/', async(req, res) => {
console.log("username:", req.body.username);
console.log("link:", req.body.link);
// if animation is already liked, then dislike it
// if it's not liked, then store it in db
const user = await User.findOne({ username: req.body.username });
if (user.likedAnimations.indexOf(req.body.link) === -1) {
user.likedAnimations.push(req.body.link);
} else {
user.likedAnimations = arrayRemove(user.likedAnimations, user.likedAnimations[user.likedAnimations.indexOf(req.body.link)]);
}
user.save();
});
function arrayRemove(arr, value) {
return arr.filter((item) => {
return item != value;
});
}
module.exports = router;
对于前五个请求,我得到以下输出:
Liked animations: ["/animations/animated-button.html"]
GET /animation-list/?username=marko 200 5.152 ms - 54
Liked animations: ["/animations/animated-button.html"]
GET /animation-list/?username=marko 304 3.915 ms - -
之后,在刷新页面之前,我在服务器控制台上没有任何输出,前端也没有任何更改,即使数据库操作仍然有效并且数据已保存。
解决方案
看来你有几个问题正在发生。首先,此请求处理程序未正确编码以处理错误,因此它将请求保留为未决状态并且不发送响应,并且连接将保持未决状态,直到客户端最终超时。其次,您可能有某种数据库并发使用错误,这是这里的根本问题。第三,您没有await
正确使用数据库。您要么使用,要么await
将回调传递给数据库,而不是两者。您需要修复所有这三个问题。
解决第一个和第三个问题:
router.get('/', async(req, res) => {
try {
let result = await User.findOne({ username: req.query.username };
if (result) {
console.log("Liked animations:", result.likedAnimations);
res.send({ animationList: result.likedAnimations });
} else {
console.log("no database result found");
res.sendStatus(404);
}
} catch(e) {
console.log(e);
res.sendStatus(500);
}
});
对于第二个问题,您提到的特定数据库错误似乎是数据库内部的某种并发/锁定问题,并且由您的代码执行的数据库操作序列触发。您可以在此处的讨论中阅读有关该错误的更多信息。由于您向我们展示的代码仅显示单个读取操作,因此我们需要查看更大的相关代码上下文,包括与写入数据库的此操作相关的代码,以便能够提供有关如何修复的任何想法这个问题的根本原因。
我们在这里看不到整个流程,但是您需要在数据库中使用原子更新操作。您显示的 PUT 处理程序是即时竞争条件。在多客户端数据库中,您不会获得值,对其进行修改然后将其写回。这是一个竞争条件的机会,因为其他人可以在您坐在他们持有它的时候修改该值。然后,当您修改持有的值时,您会覆盖其他客户刚刚所做的更改。这是一个竞赛条件。相反,您使用原子操作直接在一个数据库调用中更新操作,或者您使用事务将多步骤操作变为安全操作。
我建议你阅读这篇关于 mongodb 原子操作的文章。并且,您可能想要使用类似的东西,.findAndModify()
这样您就可以在一个原子操作中找到并更改数据库中的项目。如果搜索“mongodb 中的原子操作”,还有很多其他关于该主题的文章。
推荐阅读
- azure - Azre Data Explorer 数据连接自动化
- android - 无法在 dsl Kotlin 的构建 gradle 应用程序级别中使用 android
- android - 使用android room以mvvm模式从数据库中提取数据时在哪里放置逻辑?
- asp.net - 获取执行特定存储过程的应用程序名称
- c# - 如何设计和打印 rdlc 报告作为收据?
- r - 使用 lmer - 混合模型仅为一个嵌套组指定随机斜率
- ruby-on-rails - 结构转储和结构加载
- mysql - MySQL 基于客户的不同字段计数
- javascript - 如何在 Input 中设置值并选择
- c++ - 替代获取标准库函数的地址/可能是格式错误的行为