【问题标题】:sending POST request to express route - after receiving form data, res.render is not triggered发送 POST 请求到 express 路由 - 收到表单数据后,不会触发 res.render
【发布时间】:2020-11-10 09:32:42
【问题描述】:

我正在尝试创建一个简单的应用程序,在其中上传图片,并将该图片绘制在 html 画布上,以便我可以进行一些简单的像素操作。

现在我有 GET 方法来根渲染一个带有 fileReader 和画布的 EJS 模板。 通过脚本标签在 EJS 文件底部附加代码,我将上传的图像绘制到画布上,以便读取每个像素的 rgb 值。

然后我尝试将这些 rgb 值发送到应用程序中的 POST 路由(通过 fetch),但它没有按预期工作。

app.post("/", (req, res)=>{
    console.log("inside post");
    console.log(req.body);
    res.render("test", {result: req.body});
    console.log("after res.render");
});

所有三个控制台日志都在终端中正确打印,包括请求正文,但未呈现测试模板。它只是停留在与应用启动时相同的“索引”视图中。

有人可以告诉我为什么会发生这种情况吗?我还在 ejs 模板的脚本标签中包含了控制台日志,这些日志只显示在浏览器中,而不是在我启动 express 应用程序的终端中。如何在 post 方法中渲染视图?

【问题讨论】:

    标签: express ejs


    【解决方案1】:

    首先

    如果您使用 Fetch API 或 XHR 之类的 AJAX,浏览器将不会呈现 test 页面。
    因为它是异步的,你可以看到Ajax in MDN web docs。
    您需要使用带有以下代码的表单发布。

    <form action="/" method="post">
        <button type="submit">go to another page</button>
    </form>
    

    但是,如果您使用表单发布,您的页面可能是“index.ejs”将被替换为“test.ejs”。

    换句话说,
    浏览器使用表单 POST 请求的响应来加载新页面。
    但是浏览器将AJAX请求的响应传递给回调并在js中触发回调。
    浏览器以不同的方式处理这两种类型的请求(Form Post 和 AJAX POST)。
    共同点,两者都是向服务器发送数据。

    因此,在您的情况下,res.render 已成功触发。
    让我给你看一个例子。这是我的服务器代码。

    const express = require('express')
    const app = express()
    
    app.set("view engine", "ejs")
    
    app.get("/", (req, res, next) => {
        res.render("test")
    })
    
    app.post("/test", (req, res, next) => {
        res.render("other-test")
    })
    
    app.listen(3000)
    
    <!-- test.ejs -->
    <h1>this is test pages.</h1>
    
    <!-- other-test.ejs -->
    <h1>this is other test pages.</h1>
    

    当我输入 url http://localhost:300 时,浏览器会显示这个。

    然后我在 chrome 中打开控制台并输入以下代码。

    fetch("/test", {
      method: 'POST', // or 'PUT'
      body: JSON.stringify({}), // data can be `string` or {object}!
    }).then(res => {console.log("trigger response")})
    

    然后在 chrome 中转到网络选项卡,您将看到请求。
    在这里,这个请求触发了 express 方法。

    但是,反应是什么?

    嗯,它是一个 html。 这意味着res.render("other-test") 被正确触发。
    您会发现控制台输出显示“触发响应”,这是在我的 fetch 中触发的回调。
    而且,页面仍然停留在“test.ejs”中。

    接下来,我在 test.ejs 中添加以下代码

    <form action="/test" method="post">
        <button type="submit">Go to other page</button>
    </form>
    

    页面会是这样的。

    点击后,你会发现浏览器显示“other-test”的内容。

    这是form post和ajax post的区别。

    第二

    您将脚本标签放入 ejs 模板中。
    Express 将使用 ejs 引擎将您的 ejs 模板渲染为 html 页面。
    变成html页面后,这意味着所有脚本都在浏览器中运行,而不是你的nodejs终端。

    【讨论】:

    • 也许我理解错了 - 你是什么意思它在后台运行所以我需要使用表单发布?我很困惑,因为我使用表单 post 将数据发送到我的快速路线,并将该数据作为参数传递给 res.render() 之前。如果我使用 AJAX 发送数据以访问我的快速路由(并且可以在该路由中读取该数据),它与表单发布方法有何不同?在这两种情况下,我不只是尝试将数据发送到“app.post('/')”并尝试使用传入的数据调用 res.render 吗?
    • 我主要是解释为什么当您使用 fetch API(一种 AJAX 进行发布)时您的 express 不呈现 test.ejs。我的意思是浏览器使用表单 POST 请求的响应来加载新页面。但是 AJAX 请求的响应被传递给 js 中的回调。浏览器以不同的方式处理这两种类型的请求(Form Post 和 AJAX POST)。
    • 我明白你在说什么,我感谢你的意见,但我还是不明白。我还尝试渲染'test.ejs'而不在res.render 中的ajax 正文中传递。由于控制台日志显示我显然正在点击 'app.post("/")' 方法/路由,为什么 res.render("test") 没有触发? app.post("/", (req,res)=&gt;{res.render("test"}); res 中的对象是我们需要从 express 向客户端发送所需的 http 响应的对象吗?如果我们不使用表单/ajax 数据(req 的一部分,对吗?),表单/ajax 处理的差异如何阻止 res.render 工作?
    • form/ajax 都命中了你的 express 应用,没错。重要的是浏览器如何处理表单和 ajax。您可以看到我的新更新内容,我给您举个例子。
    猜你喜欢
    • 1970-01-01
    • 2020-11-24
    • 2020-06-05
    • 2017-12-11
    • 1970-01-01
    • 2015-09-26
    • 1970-01-01
    • 2021-12-03
    相关资源
    最近更新 更多