【问题标题】:Express server stops after 5 GET requestsExpress 服务器在 5 次 GET 请求后停止
【发布时间】:2021-04-02 07:35:06
【问题描述】:

此代码的工作方式应该可以正常工作,但是在第五次 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 - -

在刷新页面之前,我在服务器控制台上没有任何输出,前端也没有任何变化,即使数据库操作仍然有效并且数据已保存。

【问题讨论】:

  • 此请求处理程序有两个根本不发送响应的代码路径。 1) 如果 User.findOne() 失败并拒绝或 2) 如果 result 是假的(没有找到)。在这两种情况下,您都应该发送适当的响应。每当发生可疑的事情时,我要做的第一件事就是调查我的错误处理,看看是否发生了我没有正确处理的事情。此外,您可以在服务器上记录所有可能的代码路径,并查看您是否收到了请求,如果收到了,它会采用什么路径。你可以通过更多的日志记录来解决这个问题。
  • 打开 Chrome 调试器并查看网络选项卡,并查看当您发出这些似乎没有显示任何内容的客户端请求时服务器返回给您的确切内容。
  • 另外,该代码不会将任何内容保存到数据库中?
  • @ChrisG 它触发保存的代码
  • 您发布的代码仅包含一个读取 DB (User.findOne) 的查询,没有向其写入任何内容。

标签: javascript node.js reactjs typescript express


【解决方案1】:

您似乎遇到了一些问题。首先,此请求处理程序未正确编码以处理错误,因此它将请求保留为未决状态并且不发送响应,并且连接将保持未决状态,直到客户端最终超时。其次,您可能有某种数据库并发使用错误,这是这里的根本问题。第三,您没有在数据库中正确使用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);
   }
});

对于第二个问题,您提到的特定数据库错误似乎是数据库内部的某种并发/锁定问题,并且由您的代码执行的数据库操作序列触发。您可以在discussion here 中阅读有关该错误的更多信息。由于您向我们展示的代码仅显示单个读取操作,因此我们需要查看更大的相关代码上下文,包括与写入数据库的此操作相关的代码,以便能够提供有关如何修复的任何想法这个问题的根本原因。

我们在这里看不到整个流程,但是您需要在数据库中使用原子更新操作。您显示的 PUT 处理程序是即时竞争条件。在多客户端数据库中,您不会获得值,对其进行修改然后将其写回。这是一个竞争条件的机会,因为其他人可以在您坐在他们持有它的时候修改该值。然后,当您修改持有的值时,您会覆盖其他客户刚刚所做的更改。这是一个竞赛条件。相反,您使用原子操作直接在一个数据库调用中更新操作,或者您使用事务将多步操作变为安全操作。

我建议您阅读 this article 了解 mongodb 中的原子操作。而且,您可能想使用类似.findAndModify() 的东西,这样您就可以在一个原子操作中找到并更改数据库中的项目。如果你搜索“mongodb中的原子操作”,还有很多其他的文章。

【讨论】:

  • else { console.log("没有找到数据库结果"); res.sendStatus(404);我添加了这段代码,它会在一段时间后记录下来(可能是客户端连接结束时),我现在将添加其余代码
  • 希望现在更容易看到发生了什么
  • @AndrijaGajic - 是的,这就是全面错误处理和适当日志记录背后的理念。请记住,您应该从一开始就以这种方式编写服务器端代码,而不仅仅是当您有问题要调试时。我猜你也需要在任何服务器端函数写入数据库时​​使用这种类型的日志记录。
  • 那么我到底该如何解决这个问题,我的意思是我有很好的错误日志,但问题仍然存在。如果我做对了,问题是操作顺序,客户端获取旧版本的文档并尝试修改它,然后发生冲突?
  • @AndrijaGajic - 我们在这里看不到整个流程,但您可能需要使用原子更新操作。您显示的 PUT 处理程序是立即竞争条件。在多客户端数据库中,您不会获取值,修改它然后将其写回。这是比赛条件的机会。相反,您使用原子操作直接在一个数据库调用中更新操作,或者您使用事务将多步操作变为安全操作。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-09-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多