Res.Render 停止运行

发布于 2025-01-16 11:16:32 字数 2057 浏览 3 评论 0原文

抱歉,如果我分享太多(或太少!),我不确定当代码包含在这样的多个文件中时如何提供代码。

在这个小项目中,我有一个使用express和ejs的app.js服务器。我有一个“/compose”路线,它创建一个带有“标题”和“内容”的博客文章。然后它将其推送到名为“posts”的全局数组中。

在“/posts”路由中,我的意图是服务器应该循环包含帖子的“posts”数组,并将正确的帖子标题与 URL 中给出的“postName”参数相匹配。 (我试图使用字符串上的 .toLowerCase() 方法使标题不区分大小写。)

但是,当我这样做时,页面只是停止运行并且实际上没有加载。不过,一个奇怪的错误是,如果我通过对 app.js 代码进行一些小的更改(例如更改逗号或注释掉一行)来“重新加载”服务器(我正在运行 nodemon),从而使 nodemon 重新加载,页面将显示所请求的信息。

// This is my app.js code
const express = require("express");
const ejs = require("ejs");
const app = express();

app.set('view engine', 'ejs');

app.use(express.urlencoded({
  extended: true
}));
app.use(express.static(__dirname + "/public"));

const posts = [];

app.get("/posts/:postName", (req, res) => {
  const requestedTitle = req.params.postName.toLowerCase();
  posts.forEach(post => {
    const storedTitle = post.title.toLowerCase();
    if (requestedTitle === storedTitle) {
      res.render("post", {
        post: post
      });
    }
  });
});

app.post("/compose", (req, res) => {
  const post = {
    title: req.body.postTitle,
    content: req.body.postBody
  };
  posts.push(post);
  res.redirect("/")
})
<!-- This is my "Post" route HTML code (a partial called post.ejs) -->
<h1>This is
  <%= post.title%>
</h1>

<!-- This is my "Compose" route HTML Code (a partial called compose.ejs) -->
<h1>Compose</h1>
<form action="/compose" method="POST">
  <div class="form-group">
    <label for="postTitle">Title</label>
    <input class="form-control" type="text" name="postTitle" autofocus>
    <label for="postBody">Post</label>
    <textarea class="form-control" name="postBody" id="" cols="30" rows="5"></textarea>
  </div>
  <button class="btn btn-primary" type="submit" name="button">Publish</button>
</form>

Sorry if I'm sharing too much (or too little!) I'm not sure how to provide code when it's contained in multiple files like this.

In the small project I have my app.js server using express and ejs. I have a "/compose" route which creates a blog post with a "Title" and "Content". It then pushes this into a global array called "posts".

In the "/posts" route, my intention is that the server is supposed to loop over the "posts" array containing the posts and match the correct post title with the "postName" parameter given in the URL. (I am trying to make the Titles case insensitive with the .toLowerCase() method on the strings.)

However, when I do this, the page just stalls and doesn't actually load. A curious bug though is that if I "reload" the server (I'm running nodemon) by even making a small change to the app.js code such as changing a comma or commenting out a line, such that nodemon reloads, the page will display the requested information.

// This is my app.js code
const express = require("express");
const ejs = require("ejs");
const app = express();

app.set('view engine', 'ejs');

app.use(express.urlencoded({
  extended: true
}));
app.use(express.static(__dirname + "/public"));

const posts = [];

app.get("/posts/:postName", (req, res) => {
  const requestedTitle = req.params.postName.toLowerCase();
  posts.forEach(post => {
    const storedTitle = post.title.toLowerCase();
    if (requestedTitle === storedTitle) {
      res.render("post", {
        post: post
      });
    }
  });
});

app.post("/compose", (req, res) => {
  const post = {
    title: req.body.postTitle,
    content: req.body.postBody
  };
  posts.push(post);
  res.redirect("/")
})
<!-- This is my "Post" route HTML code (a partial called post.ejs) -->
<h1>This is
  <%= post.title%>
</h1>

<!-- This is my "Compose" route HTML Code (a partial called compose.ejs) -->
<h1>Compose</h1>
<form action="/compose" method="POST">
  <div class="form-group">
    <label for="postTitle">Title</label>
    <input class="form-control" type="text" name="postTitle" autofocus>
    <label for="postBody">Post</label>
    <textarea class="form-control" name="postBody" id="" cols="30" rows="5"></textarea>
  </div>
  <button class="btn btn-primary" type="submit" name="button">Publish</button>
</form>

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

这个俗人 2025-01-23 11:16:32

我看到的主要问题是您的 app.get("/posts/:postName", ...) 路由需要始终发送一个且仅一个 http 响应。按照现在的编码方式,如果找不到匹配的帖子,它将不发送任何响应;如果找到多个响应,它将尝试发送多个响应。这两个条件都是一个问题。

这是解决该问题的一种方法:

app.get("/posts/:postName", (req, res) => {
    const requestedTitle = req.params.postName.toLowerCase();
    for (let post of posts) {
        const storedTitle = post.title.toLowerCase();
        if (requestedTitle === storedTitle) {
            res.render("post", {
                post: post
            });
            return;
        }
    }
    // send some sort of response here with a 404 status
    res.sendStatus(404);
});

作为对您所看到的服务器行为的可能解释,浏览器只会同时向同一主机发送如此多的请求。因此,如果使用原始代码,您正在使用没有匹配帖子的 URL,则这些 URL 不会从服务器发送回浏览器,并且这些请求仍将等待响应。最终,浏览器将达到发送到主机的最大请求数,直到其中一些请求完成。因此,您的服务器似乎不再响应新请求,而实际上它只是在等待先前的请求完成。您必须始终从服务器向每个传入的 http 请求发送一个且仅一个响应。


我认为这个 posts 数组可能只是一个临时存储机制,但如果用一个以小写标题为键的 Map 对象替换该数组,效率会高得多。然后,您可以通过一个 map.get() 操作直接在 Map 对象上查找匹配的标题,而不是循环遍历整个数组。

The main problem I see is that your app.get("/posts/:postName", ...) route needs to always send one and only one http response. The way it is coded now, it will send no response if a matching post isn't found and it will attempt to send multiple responses if more than one is found. Both conditions are a problem.

Here's one way to fix that:

app.get("/posts/:postName", (req, res) => {
    const requestedTitle = req.params.postName.toLowerCase();
    for (let post of posts) {
        const storedTitle = post.title.toLowerCase();
        if (requestedTitle === storedTitle) {
            res.render("post", {
                post: post
            });
            return;
        }
    }
    // send some sort of response here with a 404 status
    res.sendStatus(404);
});

As a possible explanation for the server behavior you saw, the browser will only send so many requests in-flight at the same time to the same host. So, if with your original code, you are playing with URLs that don't have matching posts, those will not get responses sent back to the browser from the server and those requests will still be waiting for a response. Eventually the browser will hit the max requests that it will send to your host until some of them finish. Thus, it will appear that your server becomes non-responsive to new requests, when in reality it's just waiting for prior requests to finish. You must always send one and only one response from your server to each incoming http request.


I assume this posts array is probably just a temporary storage mechanism, but it would be a lot more efficient if you replaced the array with a Map object with the lowercase title as the key. Then, you could just directly lookup the matching title on the Map object with one map.get() operation rather than looping through the whole array.

真心难拥有 2025-01-23 11:16:32

对于从安吉拉博士的教程/课程中遇到此问题的任何人来说,我遇到了此问题并通过从我的文件中删除 来解决它“header.ejs”文件。

如果您已经在项目的终端中使用了npm install lodash,则不需要两者,因为这似乎会导致页面渲染速度严重减慢。

一旦删除,页面立即加载。

For anyone coming here with this issue from Dr Angela's tutorial/course, I had this issue and solved it by removing the <script src="lodash.js"></script> from my 'header.ejs' file.

If you've already used npm install lodash in the terminal for your project, you don't need both as it seems to cause a severe slowdown rendering the page.

Once removed the pages loaded instantly.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文