【问题标题】:My Server keeps crashing if User refreshes too much or Quick如果用户刷新太多或快速,我的服务器会不断崩溃
【发布时间】:2021-11-12 06:40:26
【问题描述】:

我很茫然,想不出怎么用谷歌搜索这个。

我正在构建一个 MERN 全栈应用程序作为我的第一个独立项目。有人告诉我它太大(他们是对的)我会被烧毁(我是)。好吧,开他们的玩笑。他们是对的。

我让服务器响应一个来自类似 4 个用户的数据库中的类似 4 个用户信息的列表作为测试。这是在前端设置为 useEffect 的,不确定是否有帮助,人们告诉我它不应该对它产生影响。

它只工作一半的时间,如果不是更少的话。其他时候服务器崩溃就像我的 Dogecoin 投资一样,说我已经使用了 res.send,这让我想把我的电脑和监视器扔到窗外,吓唬楼下的邻居,这不会那么糟糕,因为她爱管闲事,而且总是看到我的邮件,并认为她是我的邮件人。

这是服务器控制台上的错误

events.js:292
      throw er; // Unhandled 'error' event
      ^

Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
    at ServerResponse.setHeader (_http_outgoing.js:558:11)
    at ServerResponse.header (/Users/apple/Documents/Web Dev/collab/Backend/node_modules/express/lib/response.js:771:10)
    at ServerResponse.send (/Users/apple/Documents/Web Dev/collab/Backend/node_modules/express/lib/response.js:170:12)
    at ServerResponse.json (/Users/apple/Documents/Web Dev/collab/Backend/node_modules/express/lib/response.js:267:15)
    at ServerResponse.send (/Users/apple/Documents/Web Dev/collab/Backend/node_modules/express/lib/response.js:158:21)
    at /Users/apple/Documents/Web Dev/collab/Backend/routes/index.js:81:9
    at /Users/apple/Documents/Web Dev/collab/Backend/node_modules/mongoose/lib/model.js:5065:18
    at processTicksAndRejections (internal/process/task_queues.js:75:11)
Emitted 'error' event on Function instance at:
    at /Users/apple/Documents/Web Dev/collab/Backend/node_modules/mongoose/lib/model.js:5067:15
    at processTicksAndRejections (internal/process/task_queues.js:75:11) {
  code: 'ERR_HTTP_HEADERS_SENT'

Router.get(/users)

routes/index.js 文件

const router = require("express").Router();
const passport = require("passport");
const bodyParser = require("body-parser");
const genPassword = require("../lib/passwordUtils").genPassword;
const connection = require("../config/database");
const mongoose = require("mongoose");
const User = mongoose.models.User;
const isAuth = require("./authMiddleware").isAuth;
// cors is needed with router.use else you have to put routes on the app.js
const cors = require("cors");
router.use(cors({ origin: "http://localhost:3001", credentials: true }));
// const isAdmin = require("./authMiddleware").isAdmin;
router.use(bodyParser.urlencoded({ extended: false }));

/**
 * -------------- Post ROUTES ----------------
 *
 */

// router.post(
//   "/login",

//   passport.authenticate("local"),
//   (req, res) => {
//     console.log("working");
//     res.sendStatus(200);
//   }
// );
// router.post("/login", (req, res) => {
//   passport.authenticate("local", (err, user, info) => {
//     res.status(200);
//   });
// });
router.post("/login", (req, res, next) => {
  passport.authenticate("local", (err, user, info) => {
    if (err) throw err;
    if (!user) res.send("No User Exists");
    else {
      req.logIn(user, (err) => {
        if (err) throw err;
        res.send(user);
        return;
        console.log(req.user);
      });
    }
  })(req, res, next);
});

router.post("/register", (req, res) => {
  const saltHash = genPassword(req.body.repeatPassword);

  const salt = saltHash.salt;
  const hash = saltHash.hash;

  const newUser = new User({
    username: req.body.firstInput,
    fName: "",
    lName: "",
    title: "",
    hash: hash,
    salt: salt,
  });

  newUser.save().then((user) => {});
  res.sendStatus(200);
});

/**
 * -------------- GET ROUTES ----------------
 *
 */
router.get("/user", (req, res) => {
  res.send(req.user);
});
router.get("/users", (req, res) => {
  User.find({}, function (err, users) {
    const userMap = {};
    users.forEach(function (user) {
      userMap[user._id] = user;
    });
    res.send(userMap);
  });
});
router.post("/user", (req, res) => {
  const fName = req.body.firstInput;
  const lName = req.body.secondInput;

  const title = req.body.repeatPassword;

  const user = req.session.passport.user;
  User.updateOne(
    { _id: user },
    { fName: fName, lName: lName, title: title },
    function (err, result) {
      if (err) {
        res.sendStatus(401);
        console.log(err);
      } else {
        res.sendStatus(200);
      }
    }
  );
  // console.log(res.user);
});
router.get("/", isAuth);

// router.get("/logout", (req, res) => {
//   res.status(200);
//   req.logOut();
// });
// app.use((req, res) => {
//   User.findOne({ url: req.body.url })
//     .then((user) => {
//       if (!user) {
//         console.log("No user Found");
//         res.send("No user found");
//       } else {
//         console.log("user Found");
//         res.send(user).status(200);
//       }
//     })
//     .catch((err) => {
//       console.log(err);
//     });
// });
// function getUser(req, res, next) {
//   User.findOne({ url: req.body.url })
//     .then((user) => {
//       if (!user) {
//         console.log("No user Found");
//         res.status(401);
//         next();
//       } else {
//         console.log("success");
//         res.send({ user }).status(200);
//       }
//     })
//     .then((response) => console.log(response))

//     .catch((err) => {
//       console.log(err);
//     });
// }

// router.post("/visitor", getUser);

module.exports = router;

这里是路由/authMiddleware 文件

  if (req.isAuthenticated()) {
    return res.status(200).json({ user: req.user, auth: true });
  } else {
    console.log("Nope");
    res.status(401).json({ auth: false });
  }
};

// module.exports.isAdmin = (req, res, next) => {
//     if (req.isAuthenticated() && req.user.admin) {
//         next();
//     } else {
//         res.status(401).json({ msg: 'You are not authorized to view this resource because you are not an admin.' });
//     }
// }

如果需要,这里是前端 React。它比我哥哥开的卡车还丑,但我是新手,所以我妈妈想让你放松一下。

import React, { useContext, useEffect } from "react";
// import { useHistory } from "react-router-dom";

import "./loggedStyles.css";
import Dialog from "@mui/material/Dialog";
import DialogContent from "@mui/material/DialogContent";
import SecondBoard from "../../QuestionBoard/secondBoard";
import { LoginContext, DialogueContext } from "../../../Context/context";

function Logged(props) {
  const { userInfo, setUserInfo } = useContext(LoginContext);
  const { openDialogue, setDialogue } = useContext(DialogueContext);

  const [fullWidth, setFullWidth] = React.useState(true);
  const [maxWidth, setMaxWidth] = React.useState("sm");
  useEffect(() => {
    if (userInfo.fName !== "") {
      setDialogue(false);
    } else {
      setDialogue(true);
    }
  }, [userInfo, setDialogue]);

  const closeDialogue = () => {
    setDialogue(true);
  };

  useEffect(() => {
    fetch("http://localhost:3000/user", {
      method: "GET",
      credentials: "include",
      withCredentials: true,

      headers: {
        "Content-Type": "application/json",
      },
    })
      .then(function (response) {
        if (!response.ok) {
          console.log(response.status);
          throw new Error("HTTP status " + response.status);
        } else {
          return response.json();
        }
      })
      .then((data) => {
        if (userInfo.fName === "") {
          setUserInfo({
            ...userInfo,
            id: data._id,
            fName: data.fName,
            lName: data.lName,
            title: data.title,
          });
        } else {
          return;
        }
      })
      .catch((err) => console.log(err));
  }, [userInfo, setUserInfo]);

  useEffect(() => {
    fetch("http://localhost:3000/users", {
      method: "GET",
      credentials: "include",
      withCredentials: true,

      headers: {
        "Content-Type": "application/json",
      },
    })
      .then(function (response) {
        if (!response.ok) {
          console.log(response.status);
          throw new Error("HTTP status " + response.status);
        } else {
          return response.json();
        }
      })
      .then((data) => {
        console.log(data);
      })

      .catch((err) => console.log(err));
  }, []);

  return [
    <div className="wrapper">
      <Dialog
        fullWidth={fullWidth}
        maxWidth={maxWidth}
        open={openDialogue}
        sx={{ border: "solid black" }}
      >
        <DialogContent sx={{ p: 0, borderRadius: "2vw" }}>
          <SecondBoard
            header="Basic Information"
            headerText="Fill in all Information"
            firstPlaceHolder="Enter your first name here"
            secondPlaceholder="Enter your last name here"
            thirdPlaceholder="Your Title (Job/Career)"
            passwordMatchClass="noDisplay"
            fetchRoute="user"
          />
        </DialogContent>
      </Dialog>

      <div className="section">
        <div className="top_navbar">
          <h4>DashBoard</h4>
        </div>
        <div className="container">
          Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do
          eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad
          minim veniam, quis nostrud exercitation ullamco laboris nisi ut
          aliquip ex ea commodo consequat. Duis aute irure dolor in
          reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla
          pariatur. Excepteur sint occaecat cupidatat non proident, sunt in
          culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum
          dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor
          incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
          quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea
          commodo consequat. Duis aute irure dolor in reprehenderit in voluptate
          velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint
          occaecat cupidatat non proident, sunt in culpa qui officia deserunt
          mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur
          adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore
          magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation
          ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute
          irure dolor in reprehenderit in voluptate velit esse cillum dolore eu
          fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident,
          sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem
          ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
          tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim
          veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex
          ea commodo consequat. Duis aute irure dolor in reprehenderit in
          voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur
          sint occaecat cupidatat non proident, sunt in culpa qui officia
          deserunt mollit anim id est laborum.
        </div>
      </div>
      <div className="sidebar">
        <div className="profile">
          <img
            src="https://1.bp.blogspot.com/-vhmWFWO2r8U/YLjr2A57toI/AAAAAAAACO4/0GBonlEZPmAiQW4uvkCTm5LvlJVd_-l_wCNcBGAsYHQ/s16000/team-1-2.jpg"
            alt="profile_picture"
          />
          <h3>
            {userInfo.fName} {userInfo.lName}
          </h3>
          <p>{userInfo.title}</p>
        </div>
        <ul>
          <li>
            <a href="/" className="active">
              <span className="icon">
                <i className="fas fa-home"></i>
              </span>
              <span className="item">Home</span>
            </a>
          </li>
          <li>
            <a href="/">
              <span className="icon">
                <i className="fas fa-desktop"></i>
              </span>
              <span className="item">My Dashboard</span>
            </a>
          </li>
          <li>
            <a href="/">
              <span className="icon">
                <i className="fas fa-user-friends"></i>
              </span>
              <span className="item">People</span>
            </a>
          </li>
          <li>
            <a href="/">
              <span className="icon">
                <i className="fas fa-tachometer-alt"></i>
              </span>
              <span className="item">Perfomance</span>
            </a>
          </li>
          <li>
            <a href="/">
              <span className="icon">
                <i className="fas fa-database"></i>
              </span>
              <span className="item">Development</span>
            </a>
          </li>
          <li>
            <a href="/">
              <span className="icon">
                <i className="fas fa-chart-line"></i>
              </span>
              <span className="item">Reports</span>
            </a>
          </li>
          <li>
            <a href="/">
              <span className="icon">
                <i className="fas fa-user-shield"></i>
              </span>
              <span className="item">Admin</span>
            </a>
          </li>
          <li>
            <a href="/">
              <span className="icon">
                <i className="fas fa-cog"></i>
              </span>
              <span className="item">Settings</span>
            </a>
          </li>
        </ul>
      </div>
    </div>,
  ];
}
export default Logged;

编辑编辑刚刚意识到我过早地抛出了我的问题,然后才意识到我应该通知你我在 useEffect 中为 /users 获取了 Fetch,直到最近作为最后的努力来搞乱并试图找出答案。

【问题讨论】:

  • 欢迎来到全栈开发的狂野世界!除了幽默的散文之外,您能否粘贴实际错误并追溯服务器打印出来的内容(不仅仅是“说我已经使用了 res.send”)?
  • “routes/index.js”是你粘贴的路由文件吗?回溯中的第 81 行似乎与其中的发送调用不对应。
  • 没关系,不用担心。当“证据”都在那里并且正确时,提供帮助会容易得多。您可以在不删除内容的情况下发布实际代码,或者使用您发布的代码重现错误吗?
  • 您能否也添加该./authMiddleware 文件?我感觉里面的东西可能正在发送响应...
  • 是的——如果你有一个带有那个中间件的app.use(...)(你仍然省略了将这个路由器连接到一个 Express 应用程序的主文件,这就是那个地方),它不会去工作,因为中间件总是会在实际的处理程序有机会做它的事情之前发送响应。

标签: javascript node.js reactjs express


【解决方案1】:

在 cmets 中展开讨论...

const isUser = (req, res, next) => {
  if (req.isAuthenticated()) {
    return res.status(200).json({ user: req.user, auth: true });
  } else {
    console.log("Nope");
    res.status(401).json({ auth: false });
  }
};

该身份验证中间件无条件发送响应,因此使用该中间件的路径中的任何实际处理程序都无法发送另一个响应。

在快乐的情况下,auth 中间件可能不会发送响应,并且应该调用next(),因此路由被调用。这在Express's docs 中有很好的解释。

【讨论】:

  • 成功了。在这里,我向所有人和我自己大喊我是 DEF 没有重新发送两次。
  • 很高兴我能帮上忙!如果您还没有,我建议您设置 ESlint 和 Prettier 工具来帮助您解决潜在的错误并格式化您的代码。
  • 我也一定会调查的。我比我想象的更漂亮了。
【解决方案2】:

可能不是原因,但这似乎是错误的,您可能打算在 res.send 部分周围加上大括号。

if (!user) res.send("No User Exists");
else {
  req.logIn(user, (err) => {
    if (err) throw err;
    res.send(user);
    return;
    console.log(req.user);
  });
}

【讨论】:

  • 很棒的收获。这很时髦。我不知道我为什么那样做。谢谢!
  • 如果你的意思是第一个res.send,这里应该没关系。
  • 是的,但我修复了它,无论如何它都有帮助。
猜你喜欢
  • 1970-01-01
  • 2014-12-20
  • 1970-01-01
  • 2019-11-07
  • 2015-06-27
  • 1970-01-01
  • 2014-11-30
  • 2020-06-15
  • 1970-01-01
相关资源
最近更新 更多