为什么在快速路由中调用 next() 是可选的?

Why calling next() in express routes is optional?

Nodejs/Express 的许多示例中,我看到如果成功,调用 next() 是可选的。

 exports.postLogin = (req, res, next) => {
  passport.authenticate("local", (err, user, info) => {
    if (err) {
      return next(err);
    }
    req.logIn(user, err => {
      if (err) {
        return next(err);
      }
      req.flash("success", { msg: "Success! You are logged in." });
      res.redirect(req.session.returnTo || "/");
    });
  })(req, res, next);
};

此外,在 args:

中跳过回调 next 很容易
exports.postLogin = (req, res) => {
   res.render('some-template', locals);
}

如果我将其与 async 库或典型的 Javascript 的异步模型进行比较,缺少的回调将不会提供数据或停止进程。

next 未被调用时,express 如何处理控制流?

next 用于将请求传递给其他(可能的)处理程序。如果你正在编写一个中间件或(不太可能)不想处理请求的路由处理程序,你可以调用 next 并让 Express 解决它。也许还有其他中间件或其他路由处理程序可以处理它。

如果您的代码 确实 处理请求,这意味着它会发回响应,则您不应调用 next。 Express 不关心这个:在内部,中间件和路由处理程序存储在一个数组中,Express 检查每个项目以查看它是否可以处理请求。它传递 next 函数,以便它可以被告知尝试下一个匹配的处理程序。但它是可选的。

它还用于将错误传递给 Express,因此它可以将错误传递给全局错误处理程序。这就是当您看到 next(err) 被调用时发生的情况。

Express 中间件链中的真正回调实际上并不是您可能假设的 next,而是 res.end()。任何被处理的请求都必须在某个时候调用此函数(直接或间接)以表明请求已被处理。

当您在中间件中调用 next() 时,您将调用 res.end() 的责任传递给中间件链下游的中间件。如果链中的最后一个中间件调用 next(),那么 Express 知道没有中间件已经或将要处理该请求,因此将生成“404 Not Found”页面。


此外,使用单个参数 err 调用 next(err) 的工作方式不同,因为它告诉 Express 发生了错误,应该由错误处理程序处理。

next 当您想将控制传递给 next 中间件时调用。

由于中间件的顺序声明是相关的,express 将只负责验证您的函数的参数,如果找到第三个参数,它将传递一个指向后续中间件的指针。

如果您 return 将结果发送给客户端(例如调用 res.render),则不需要调用 next,因此不需要将 next 作为第三个参数。