【问题标题】:What is the reason that Asnyc Express Midleware works?Async Express Middleware 工作的原因是什么?
【发布时间】:2020-07-23 21:12:11
【问题描述】:

您好,我是 Express/Node 的新手,正在寻找指导和解释。

如果我有一个 asyc 函数作为中间件,这本质上会立即返回一个 Promise。让我们模拟一个函数。

async function verifyToken() {
    try {
        await API call...
        next() // <-- continue to the next middleware if the api call was successful
    } catch (err) {
        // catch exceptions from api call
        }
    }

我现在想知道什么时候像这样使用这个功能:

 this.router.get("/test", verifyToken, (req, res) => {
 res.send("GET TEST");
});

如果 verifyToken 是异步的,这是否意味着它会立即被调用并返回一个 Promise,然后节点继续执行?异步方法如何作为中间件工作?

【问题讨论】:

  • 它会立即被调用,但只要有 await 关键字,代码就会重新编译成 API call.then(next),因此无论是否调用过 .then()await 都将始终有效。对于任何承诺返回函数都是如此。尝试在中间件之外自己调用verifyTokenverifyToken({},{},()=&gt;console.log('next was called'))

标签: node.js express asynchronous promise async-await


【解决方案1】:

当请求到达您的应用程序时,它首先到达您的应用程序中间件,然后到达路由器中间件,最后到达路由器定义的函数。 执行中间件时,如果调用 next() 函数,它只会将请求传递到下一步。应用程序的任何部分都不会读取或使用中间件返回的值(如果它返回某些内容)。 我认为中间件是否异步根本不重要,因为 express 只会在调用 next() 函数后继续执行。

【讨论】:

    【解决方案2】:

    如果 verifyToken 是异步的,这是否意味着它被立即调用并返回一个 Promise 然后节点继续执行?异步方法如何作为中间件工作?

    你是对的,async 函数在遇到 await 内部时会立即返回一个 Promise。但是,即使 Express 没有注意那里的返回承诺,由于 Express 的设计,它仍然可以正常工作。

    Express 在其设计中预计需要异步中间件(无论是否使用 Promise)。因此,它调用您的中间件,将reqres 对象和next 回调传递给它,然后什么也不做。字面上没什么。此时会进行进一步处理,直到您执行以下两项操作之一 - 发送带有 res.send() 之类的响应或致电 next()。如果您发送响应,那是非常不言自明的。如果你调用next(),那么这会告诉 Express 跟踪该请求的处理程序链并找到下一个匹配的请求处理程序并调用它。

    所以,以下是这条路线匹配的步骤:

    async function verifyToken(req, res, next) {
        try {
            await API call...
            next() // <-- continue to the next middleware if the api call was successful
        } catch (err) {
            // catch exceptions from api call
        }
    }
    
    this.router.get("/test", verifyToken, (req, res) => {
        res.send("GET TEST");
    });
    
    1. nodejs 首先调用verifyToken() 并传递给req, res, next
    2. 该函数命中 await,进行 API 调用,暂停该函数的进一步执行,然后立即返回一个未决的承诺
    3. 返回返回到 Express,它只是返回到通知它传入请求的任何网络事件,那里没有其他事情可做。
    4. 然后,有一段时间什么都没有发生。
    5. 然后,您的 API 调用在某个时间点完成,等待的承诺得到解决。这将在 await 之后的代码行处重新启动函数的执行。
    6. 它调用next(),它返回到Express,并使用next()回调的闭包中的数据,它知道接下来要调用哪个处理程序,它会调用你的路由中的最终请求处理程序,它调用res.send()
    7. 该处理程序返回并且 Express 完成。由于您没有从最后一个处理程序调用 next(),因此 Express 将不再处理该请求。

    Express 是不久前设计的,因此并非天生具有承诺意识。但是,它在设计时考虑了异步操作,因此 Promise 仍然可以很好地与框架一起使用——您只需将 Promise 事件处理程序连接到适当的 Express 回调。因为 express 没有关注您的 async 函数返回的承诺,所以您必须确保自己捕获所有拒绝,因为 Express 不会为您捕获它们。

    Express 有一个名为 koa 的表亲,它更多地围绕 Promise 进行设计,并且对被拒绝的 Promise 具有自动错误处理功能。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-04-10
      • 1970-01-01
      • 2021-11-23
      • 2017-04-29
      • 1970-01-01
      • 2011-09-02
      相关资源
      最近更新 更多