代码之家  ›  专栏  ›  技术社区  ›  Rammah_N

为什么我的Heroku Express API数据是持久的,即使它只来自一个变量

  •  2
  • Rammah_N  · 技术社区  · 2 年前

    我使用express创建了一个简单的API,并将其部署到Heroku,代码如下:

    const express = require("express");
    const app = express();
    const cors = require("cors");
    app.use(express.json());
    app.use(cors());
    app.use(express.static("build"));
    let notes = [
        {
            id: 1,
            content: "HTML is easy",
            date: "2022-05-30T17:30:31.098Z",
            important: true,
        },
        {
            id: 2,
            content: "Browser can execute only Javascript",
            date: "2022-05-30T18:39:34.091Z",
            important: false,
        },
        {
            id: 3,
            content: "GET and POST are the most important methods of HTTP protocol",
            date: "2022-05-30T19:20:14.298Z",
            important: true,
        },
    ];
    
    const generateId = (arr) => {
        const maxId = arr.length < 0 ? 0 : Math.max(...arr.map((item) => item.id));
        return maxId + 1;
    };
    
    app.get("/", (req, res) => {
        res.send(`<h1>Hello World!</h1>`);
    });
    
    app.get("/api/notes", (req, res) => {
        res.json(notes);
    });
    
    app.get("/api/notes/:id", (req, res) => {
        const id = Number(req.params.id);
        const note = notes.find((note) => note.id === id);
        if (note) {
            res.json(note);
        } else {
            res.status(404).end();
        }
    });
    
    app.delete("/api/notes/:id", (req, res) => {
        const { id } = Number(req.params);
        notes = notes.filter((note) => note.id !== id);
        res.status(204).end();
    });
    
    app.post("/api/notes", (req, res) => {
        const body = req.body;
        if (!body.content) {
            return res.status(400).json({
                error: "Content Missing",
            });
        }
        const note = {
            content: body.content,
            important: body.important || false,
            date: new Date(),
            id: generateId(notes),
        };
        notes = notes.concat(note);
        res.json(note);
    });
    
    app.put("/api/notes/:id", (req, res) => {
        const newNote = req.body;
        notes = notes.map((note) => (note.id !== newNote.id ? note : newNote));
        res.json(newNote);
    });
    
    const PORT = process.env.PORT || 3001;
    app.listen(PORT, () => {
        console.log(`Server running on port ${PORT}`);
    });
    
    

    如您所见,提供给前端(React应用程序)的数据来自“/api/notes”端点,该端点使用notes数组返回响应。
    部署到Heroku后( https://fierce-chamber-07494.herokuapp.com/ )添加注释和设置重要性的功能都非常正常,但我没有想到的是,即使在刷新页面、在其他设备中访问页面等之后,数据也会保持不变。数据只来自变量,而不是数据库,什么都没有。那么,为什么它会持续存在呢?Heroku是否修改变量本身?这是如何工作的? 我希望我的问题很清楚。

    1 回复  |  直到 2 年前
        1
  •  2
  •   CertainPerformance    2 年前

    Express服务器的顶级代码通常在启动服务器时运行一次。如果有任何处理程序引用该顶级声明的变量,则该顶级声明的变量是持久的。

    考虑使用JavaScript的客户端页面是如何工作的——页面加载,然后JavaScript运行。如果您将选项卡保持打开状态几个小时,然后再返回,您将看到在pageload上声明的变量在返回时仍然存在。这里也发生了类似的事情,只是持久化环境位于服务器上,而不是客户端页面上。

    启动Express server的代码—即

    const express = require("express");
    const app = express();
    const cors = require("cors");
    app.use(express.json());
    app.use(cors());
    ...
    

    下面的一切都无法运行 每次向服务器发出请求时 . 相反,它运行 一旦 ,当服务器启动时,然后在发出请求时,会调用请求处理程序,例如内部的回调

    app.get("/", (req, res) => {
        res.send(`<h1>Hello World!</h1>`);
    });
    

    因此,在顶层声明的变量是持久的(甚至跨不同的请求),因为服务器环境是持久的。

    这就是说,Heroku需要记住的一点是,对于他们的免费和廉价层,如果在一段时间内(可能是30分钟)没有向你的应用程序发出请求,Heroku将关闭你的服务器,关闭dyno直到发出另一个请求,这时他们将再次启动你的服务器,这将再次运行顶级代码。所以当你 有时 查看一个顶层变量,该变量的变异值似乎在多个请求中保持不变,如果您的Heroku计划不能保证服务器100%正常运行,那么就不能指望这个变量。