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

时间:2012-05-22 04:11:38

标签: node.js express

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

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实际上在做什么?

6 个答案:

答案 0 :(得分:234)

它将控制传递给下一个匹配路由。例如,在您给出的示例中,如果给出了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上进行测试)是一个更灵活和强大的工具,但在我看来,因为它不依赖在特定的URI方案或路由排序上。我倾向于对这样的示例进行建模,假设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');
});

希望这能给你一些启发!

答案 1 :(得分:62)

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

export class Home implements OnInit {
    constructor(
        private route: ActivatedRoute
    ) {}

    ngOnInit(){
        let country = this.route.snapshot.params['country'];
        console.log(country) // undefined :(
    }
}  

答案 2 :(得分:34)

在理解 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();

  

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

答案 3 :(得分:6)

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

答案 4 :(得分:4)

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

答案 5 :(得分:0)

执行next函数会通知服务器您已完成此中间件步骤,并且可以执行链中的下一步。