首页 文章

Express中使用的参数“next”是什么?

提问于
浏览
221

假设您有一个简单的代码块,如下所示:

app.get('/', function(req, res){
    res.send('Hello World');
});

此函数有两个参数 reqres ,分别代表请求和响应对象 .

另一方面,还有其他函数带有第三个参数 next . 例如,让我们看看以下代码:

app.get('/users/:id?', function(req, res, next){ // Why do we need next?
    var id = req.params.id;
    if (id) {
        // do something
    } else {
        next(); // What is this doing?
    }
});

我无法理解 next() 的重点是什么或为什么使用它 . 在那个例子中,如果id不存在, next 究竟在做什么?

5 回答

  • 19

    它将控制权传递给下一个 matching 路线 . 例如,在给出的示例中,如果给出 id ,则可以在数据库中查找用户,并将其分配给 req.user .

    下面,你可以有一条路线:

    app.get('/users', function(req, res) {
      // check for and maybe do something with req.user
    });
    

    由于/ users / 123将首先匹配您示例中的路由,因此将首先检查并查找用户 123 ;然后 /users 可以做一些结果 .

    Route middleware(注意:链接是2.x文档,但这是在3.x上运行的测试)是一个更灵活和更强大的工具,但在我看来,因为它没有倾向于模拟显示的示例这个,假设 Users 模型带有异步 findOne()

    function loadUser(req, res, next) {
      if (req.params.userId) {
        Users.findOne({ id: req.params.userId }, function(err, user) {
          if (err) {
            next(new Error("Couldn't find user: " + err));
            return;
          }
    
          req.user = user;
          next();
        });
      } else {
        next();
      }
    }
    
    // ...
    
    app.get('/user/:userId', loadUser, function(req, res) {
      // do something with req.user
    });
    
    app.get('/users/:userId?', loadUser, function(req, res) {
      // if req.user was set, it's because userId was specified (and we found the user).
    });
    
    // Pretend there's a "loadItem()" which operates similarly, but with itemId.
    app.get('/item/:itemId/addTo/:userId', loadItem, loadUser, function(req, res) {
      req.user.items.append(req.item.name);
    });
    

    能够像这样控制流量非常方便 . 您可能希望某些页面仅对具有admin标志的用户可用:

    /**
     * Only allows the page to be accessed if the user is an admin.
     * Requires use of `loadUser` middleware.
     */
    function requireAdmin(req, res, next) {
      if (!req.user || !req.user.admin) {
        next(new Error("Permission denied."));
        return;
      }
    
      next();
    }
    
    app.get('/top/secret', loadUser, requireAdmin, function(req, res) {
      res.send('blahblahblah');
    });
    

    希望这能给你一些灵感!

  • 220

    我也有问题理解next(),但this帮助

    var app = require("express")();
    
    app.get("/", function(httpRequest, httpResponse, next){
        httpResponse.write("Hello");
        next(); //remove this and see what happens 
    });
    
    app.get("/", function(httpRequest, httpResponse, next){
        httpResponse.write(" World !!!");
        httpResponse.end();
    });
    
    app.listen(8080);
    
  • 59

    在理解 next 之前,您需要对节点中的请求 - 响应周期有一点了解,但不是很详细 . 它从您为特定资源发出HTTP请求开始,当您将响应发送回用户时,即当您遇到res.send('Hello World')之类的内容时,它会结束;

    让我们来看一个非常简单的例子 .

    app.get('/hello', function (req, res, next) {
      res.send('USER')
    })
    

    这里我们不需要next(),因为resp.send将结束循环并将控制权移交给路由中间件 .

    现在让我们来看看另一个例子 .

    app.get('/hello', function (req, res, next) {
      res.send("Hello World !!!!");
    });
    
    app.get('/hello', function (req, res, next) {
      res.send("Hello Planet !!!!");
    });
    

    这里我们有2个中间件函数用于相同的路径 . 但你总会从第一个得到回应 . 因为它首先安装在中间件堆栈中,res.send将结束循环 .

    但是如果我们总是不想要“Hello World !!!!”回复怎么办呢 . 在某些情况下,我们可能想要“Hello Planet !!!!”响应 . 让我们修改上面的代码,看看会发生什么 .

    app.get('/hello', function (req, res, next) {
      if(some condition){
        next();
        return;
      }
      res.send("Hello World !!!!");  
    });
    
    app.get('/hello', function (req, res, next) {
      res.send("Hello Planet !!!!");
    });
    

    什么是 next 在这做什么 . 是的,你可能有gusses . 如果条件为真,它将跳过第一个中间件函数并调用下一个中间件函数,并且您将获得 "Hello Planet !!!!" 响应 .

    因此,接下来将控件传递给中间件堆栈中的下一个函数 .

    如果第一个中间件函数没有发回任何响应但是执行一个逻辑然后从第二个中间件函数得到响应,该怎么办?

    如下所示: -

    app.get('/hello', function (req, res, next) {
      // Your piece of logic
      next();
    });
    
    app.get('/hello', function (req, res, next) {
      res.send("Hello !!!!");
    });
    

    在这种情况下,您需要调用两个中间件函数 . 因此,到达第二个中间件函数的唯一方法是调用next();

    如果你不拨打下一个电话怎么办?不要指望第二个中间件函数会自动调用 . 在调用第一个函数后,您的请求将被挂起 . 第二个函数永远不会被调用,你不会得到回复 .

  • 6

    Next用于将控制传递给下一个中间件函数 . 如果不是,请求将被挂起或打开 .

  • 4

    调用此函数会调用应用程序中的下一个中间件函数 . next()函数不是Node.js或Express API的一部分,而是传递给中间件函数的第三个参数 . next()函数可以命名为任何东西,但按照惯例,它总是被命名为“next” .

相关问题