【问题标题】:fs.writefile is making POST request loop infinitly within my express appfs.writefile 在我的快速应用程序中无限地发出 POST 请求循环
【发布时间】:2020-04-15 04:14:00
【问题描述】:

我有这个当前的服务器代码:

const express = require("express")
const fs = require("fs")
const router = express.Router()
const path = require("path")

const todos = JSON.parse(fs.readFileSync(path.join(__dirname, "../db", "todolist.json"), "utf8"))

router.get("/", async (req, res) => {
    res.send(todos)
})

router.post("/new", async (req, res) => {
    const { title, description } = req.body

    const todoItem = {
        id: "3",
        title,
        description
    }

    todos.todos.push(todoItem)

    const data = JSON.stringify(todos, null, 2)

    fs.writeFile(path.join(__dirname, "../db", "todolist.json"), data, () => {}) 
    res.status(201).json(todoItem)
})

客户:

console.log("Hello world!")

const somedata = {
    title: "A new boy",
    description: "Recieved from the client"
}

const main = async () => {
    const response1 = await fetch("http://localhost:3000/todo", {
        method: "GET",
    })
    const data1 = await response1.json()

    const response2 = await fetch("http://localhost:3000/todo/new", {
        method: "POST",
        body: JSON.stringify(somedata), 
        headers: {
            'Content-Type': 'application/json',
            "Accept": "application/json"
        }
    })

    const data2 = await response2.json()

    return { data1, data2 }
}

main().then(data => console.log(data))

当我发出 /POST 请求以创建新实体时,浏览器只会一遍又一遍地循环请求,直到我必须手动退出服务器。如果我出于某种原因使用邮递员,则不会发生这种情况。是否有人在这里看到有关 writeFile 方法的使用方式以及为什么它不断重新加载浏览器以继续推送 POST 请求的任何明显错误?

谢谢! :)

【问题讨论】:

  • 您发布的服务器代码中是否缺少某些内容?它只显示/ 获取路线和/todo 发布路线。但是,客户端代码显示了一个到 /todo 的 GET 和一个到 /todo/new 的 POST?
  • 我正在使用快速路由器功能,在 server.js 中(此处不包含),您可以像这样指定路由,但这不是问题的一部分。

标签: node.js google-chrome express fs


【解决方案1】:

我遇到了同样的问题!我花了大约 1 个小时才明白我的问题是什么:

如果使用“live server extension”,每次在项目文件夹中写入、更改或删除文件时,服务器都会重新启动!

所以,如果你的 node-app 写入文件,live-server 将重新启动并且应用程序再次写入文件! => 循环

就我而言,我编写了一个 pdf 文件。我所要做的就是告诉实时服务器扩展忽略 pdf 文件:

所以我只是添加到“settings.json”:

"liveServer.settings.ignoreFiles":["**/*.pdf"]

【讨论】:

    【解决方案2】:

    我分享了我的工作示例。body-parser 依赖项需要在发布请求中获取正文。请不要更改 server.js 中的顺序。请检查并告诉我。 并检查一次您的客户端代码是否在循环中。

    我的 server.js

    const express = require("express")
    const fs = require("fs")
    const router = express.Router()
    const path = require("path")
    const app = express();
    const bodyParser = require("body-parser")
    const todos = JSON.parse(fs.readFileSync(path.join(__dirname, "../db", "todolist.json"), "utf8"))
    
    app.use(bodyParser.json());
    
    app.use("/",router)
    router.get("/todo", async (req, res) => {
        res.send(todos)
    })
    
    router.post("/todo/new", async (req, res) => {
        const { title, description } = req.body
        const todoItem = {
            id: "3",
            title,
            description
        }
    
        todos.todos.push(todoItem)
        const data = JSON.stringify(todos, null, 2)
        fs.writeFile(path.join(__dirname, "../db", "todolist.json"), data, () => {})
        res.status(201).json(todoItem)
    });
    
    app.listen(3000, () => {
        console.log(`Server running in Port`);
    });
    

    tod​​olist.json

    {
      "todos": []
    }
    

    【讨论】:

      【解决方案3】:

      我想我找到了问题所在。当我将客户端和服务器放在不同的端口上时,实时服务器扩展似乎把事情搞砸了,使得浏览器刷新以某种方式发出的每个请求。我切换回他们共享端口,然后让它工作。我必须找到一种在以后不发生此错误的情况下将它们分开的好方法,但那是另一次了。

      感谢您的帮助:)

      【讨论】:

      • 是的,热重载并不总是按预期工作:)
      【解决方案4】:

      fs.writeFile 是异步函数。因此,要发送写入的响应after 文件,您必须在回调中执行此操作。当然,不要忘记错误检查。即

      router.post("/new", async (req, res) => {
          const { title, description } = req.body
      
          const todoItem = {
              id: "3",
              title,
              description
          }
      
          todos.todos.push(todoItem)
      
          const data = JSON.stringify(todos, null, 2)
      
          fs.writeFile(path.join(__dirname, "../db", "todolist.json"), data, (err) => {
         if(err) {
             throw err;
          }
         res.status(201).json(todoItem)
        }) 
       })
      

      或者你可以像前面提到的Muhammad一样使用fs.writeFileSync

      【讨论】:

      • 谢谢,但我已经尝试了这两种解决方案,但它们都没有帮助:(回调没有返回错误,即使我最初是这么认为的,使用同步方法也没有改变它
      • 好的,我会尝试重现您的问题并回复您
      • 请注意,我的服务器在 PORT 3000 上,而我的客户端在 PORT 5500 实时服务器扩展上(使用 cors 传输请求),但这不应该发生吗?
      【解决方案5】:

      我认为您应该使用fs.writeFileSync() 或在其回调中编写一些代码

      【讨论】:

      • 我也试过了,但不幸的是没有用。带或不带回调的 writefilesync 和 writefile 都不起作用,它们都会循环浏览器以刷新并不确定地发出新的 post 请求。如果我使用其他类型的客户端(例如邮递员),则不会发生这种情况,然后它会按预期工作。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-04-02
      • 1970-01-01
      • 2013-10-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-03-13
      相关资源
      最近更新 更多