代码之家  ›  专栏  ›  技术社区  ›  Chizaram Igolo

建议使用Express应用程序吗。是否在异步回调中使用()方法调用?

  •  0
  • Chizaram Igolo  · 技术社区  · 2 年前

    我的问题要求就最佳做法提出建议。

    我编写了一个简单的Express服务器,它创建了一个JWT,并在它(客户端)遇到API路由时将其发送给客户端。

    我将路由处理程序保存在一个单独的模块中,并从那里导出它,因为我希望使代码尽可能模块化。我把 app.use() 调用,该调用在的回调中为该路由使用中间件 signJWT() 虽然这很有效,但我需要知道这是否是一个好的做法。我这样做是因为要发回的响应需要JWT签名并准备就绪,而这本身就是一个异步操作。如果这不是一个好办法,那就是 应用程序。使用() 在异步回调中调用时,我想知道一种更好的方法,无需在与服务器条目文件相同的文件中声明路由处理程序( app.js )密码。

    这里有两个主要文件要检查; 应用程序。js公司 routes.js . 我已经包含了第三个文件中的代码——我的客户端JavaScript文件( script.js )只是为了上下文。

    1. 应用程序。js公司 (服务器+应用程序范围的中间件使用):

    const express = require("express");
    const app = express();
    const path = require("path");
    
    // JWT Library
    const jose = require("jose");
    
    // library for generating symmetric key for jwt
    const { createSecretKey } = require("crypto");
    
    // Route handler
    const routes = require("./routes");
    
    // Create key 
    const secretKey = createSecretKey("MySecret", "utf-8"); 
    
    // Sign the token
    async function signJWT() {
      const jwt = await new jose.SignJWT({
        "urn:example:claim": true,
      })
        .setProtectedHeader({ alg: "HS256" })
        .setExpirationTime("1h")
        .sign(secretKey);
    
      return jwt;
    } 
    
    // Expose static content
    app.use(express.static(path.join(__dirname, "public"))); 
    
    // This works but is this okay?
    signJWT().then((jwt) => app.use("/login", routes({ jwt: jwt })));
    
    app.listen(81); 
    console.log("Listening on port 81"); 
    

    有问题的回调:

    应该 应用程序。使用() 甚至被召回?

    // This works but is this okay?
    signJWT().then((jwt) => app.use("/login", routes({ jwt: jwt }))); 
    

    我最初尝试这样做,但是 signJWT() 我们还没有准备好,这是可以理解的:

    app.use("/login", routes({ jwt: signJWT() }));  
    

    当然,这很有效-我最初使用它,但我不想弄乱 应用程序。js公司 使用路由处理程序声明:

    app.get("/login", async function (req, res) {
      const jwt = await signJWT();
      res.json({ jwt: jwt });
    });
    

    2. 路线。js公司 (路由处理程序文件):

    const express = require("express"); 
    const router = express.Router();
    
    const wrapper = function (route_params) {
    
      router.get("/", function (req, res) {
        res.json(route_params);
      });
    
      return router;
    };
    
    module.exports = wrapper; 
    

    3. 剧本js公司 (客户端JavaScript):

    document.getElementById("btn").onclick = function () {
      makeRequest("/login");
    }; 
    
    function makeRequest(url) {
      fetch(url, {
        headers: {
          "Content-Type": "application/json",
          Accept: "application/json",
        },
      })
        .then((res) => res.json())
        .then((json) => console.log(json));
    } 
    

    示例输出(在客户端的浏览器控制台中):

    {jwt: 'eyJhbGciOiJIUzI1NiJ9.eyJ1cm46ZXhhbXBsZTpjbGFpbSI6d…Dk3fQ.0C_n25RPQNAP-wxy9PHmpo4SRtXBiiHn0fxGPspqxQM'}

    尽管这样做有效,但在 应用程序。使用() 异步回调中的调用感觉 哈奇 对我来说,这看起来可能会在以后导致问题,至少对我来说,因为Express对顶级代码的执行取决于异步回调。

    是否有更好的方法来声明此调用并从 signJWT() 以使其在路由处理程序中可用?

    非常感谢。

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

    本声明:

    signJWT().then((jwt) => app.use("/login", routes({ jwt: jwt })));
    

    很好。但是,这意味着 /login 不会立即定义路由处理程序,并且您的服务器将在没有定义该路由的情况下实际启动。虽然这不太可能在现实世界中引起太多问题,但在异步操作完成之前不启动服务器在技术上更安全,如下所示:

    signJWT().then((jwt) => {
        app.use("/login", routes({ jwt: jwt }));
        app.listen(81); 
        console.log("Listening on port 81"); 
    });
    

    建议使用Express应用程序吗。是否在异步回调中使用()方法调用?

    这不是编写Express代码的常见方法,但在技术上并没有什么问题。如果设置路由定义依赖于某个异步操作,而您没有访问顶层的权限 await ,则这是您的选择之一。其他选项是首先收集所有异步信息,然后在一个主回调内一起定义所有路由。然后,当您在一个代码块中按顺序定义所有路由时,感觉更加自然。

    这是:

    app.get("/login", async function (req, res) {
      const jwt = await signJWT();
      res.json({ jwt: jwt });
    });
    

    工作方式完全不同。此调用 signJWT() 在每个 /登录名 请求,而之前的调用仅在启动时调用一次。因此,您需要决定需要哪种体系结构,并使用该版本的代码。上面的第一个代码块调用 signJWT() 仅在服务器启动时一次。此版本为 /登录名 要求

    建议使用Express应用程序吗。是否在异步回调中使用()方法调用?

    那很好。Express根本不关注 app.use() 回调,所以无论您是返回承诺还是不返回任何内容,还是返回一些随机值,都无关紧要。同样,当回调返回时,Express也不会执行任何操作,因此不等待返回的承诺得到解决也没关系。仅当您手动呼叫时,Express才继续进行路线匹配 next() ,所以它又一次忽视了承诺 async 函数返回(这很好)。因此,如果您的代码通过使用 异步 回拨,很好。您确实需要知道,您的处理程序完全负责捕获自己的拒绝,因为Express不会为您捕获它们。有些人使用Express的包装器来捕获拒绝(并将其转换为5xx错误状态)。