快递下一个功能,它真正适用于什么?

And*_*all 110 node.js express

一直在试图找到next()方法所做的很好的描述.在Express文档中,它表示next('route')可以用于跳转到该路由并跳过其间的所有路由,但有时会next在没有参数的情况下调用.有谁知道一个描述next函数的好教程等?

Ale*_*yne 148

next()没有参数说"开玩笑,我真的不想处理这个".它会重新进入并尝试找到匹配的下一条路线.

这很有用,比如说你想要一些带有url slugs的页面管理器,还有很多其他东西,但这里有一个例子.

app.get('/:pageslug', function(req, res, next){
  var page = db.findPage(req.params.pageslug);
  if (page) {
    res.send(page.body);
  } else {
    next();
  }
});

app.get('/other_routes', function() {
  //...
});
Run Code Online (Sandbox Code Playgroud)

构成代码应该检查数据库中是否存在具有特定id slug的页面.如果它找到一个渲染它!如果找不到,则忽略此路由处理程序并检查其他路由处理程序.

所以next()没有参数允许假装你没有处理路线,所以其他东西可以取而代之.


或者是一个打击计数器app.all('*').这允许您执行一些共享设置代码,然后转到其他路由以执行更具体的操作.

app.all('*', function(req, res, next){
  myHitCounter.count += 1;
  next();
});

app.get('/other_routes', function() {
  //...
});
Run Code Online (Sandbox Code Playgroud)

  • @AndreasSelenwall`next('route')`特定于[`app.VERB()`](http://expressjs.com/api.html#app.VERB),当路由有多个回调时使用*绕过剩余的路由回调.*"`next(err)`用于跳转到任何"[错误中间件](http://stackoverflow.com/a/7151775/15031)"(`E`来自这个帖子). (7认同)
  • 在没有参数的情况下调用`next()`并不能真正告诉系统"我不想处理这个",它只是告诉系统在完成这个之后继续处理任何剩余的中间件.调用`next()`不是错误条件,它是正常流程的一部分.如果你不调用`next()`,根本不会处理其他路由. (6认同)
  • Upvoted.只是为了这个短语:"开玩笑,我实际上并不想处理这个问题"你让我明白我在寻找什么.我看到了很多类似的问题,并在一个短语中找到了解决方案. (5认同)
  • 我希望这个网站上的更多答案是为外行人写的...'next() 没有参数说“只是开玩笑,我实际上不想处理这个”' - 非常适合菜鸟...(@d512 有一个不过有更好的解释) (2认同)

Pic*_*els 120

在大多数框架中,您会收到请求并希望返回响应.由于Node.js的异步特性,如果你正在做非平凡的事情,你会遇到嵌套回调的问题.为了防止这种情况发生,Connect.js(在v4.0之前,Express.js是connect.js之上的一个层)有一些叫做中间件的东西,它是一个带有2,3或4个参数的函数.

function (<err>, req, res, next) {}
Run Code Online (Sandbox Code Playgroud)

您的Express.js应用程序是这些功能的堆栈.

在此输入图像描述

路由器很特殊,它是允许您为某个URL执行一个或多个中间件的中间件.所以它是堆栈内的堆栈.

那接下来做什么呢?很简单,它告诉您的应用程序运行下一个中间件.但是当你把东西传给下一个时会发生什么?Express将中止当前堆栈并将运行具有4个参数的所有中间件.

function (err, req, res, next) {}
Run Code Online (Sandbox Code Playgroud)

此中间件用于处理任何错误.我喜欢做以下事情:

next({ type: 'database', error: 'datacenter blew up' });
Run Code Online (Sandbox Code Playgroud)

有了这个错误,我可能会告诉用户出错了并记录真正的错误.

function (err, req, res, next) {
   if (err.type === 'database') {
     res.send('Something went wrong user');
     console.log(err.error);
   }
};
Run Code Online (Sandbox Code Playgroud)

如果你将Express.js应用程序描绘成一个堆栈,你可能会自己解决很多怪异问题.例如,当您在路由器之后添加Cookie中间件时,您的路由将不会有cookie.

  • 你在哪里存储这个匿名日志记录功能? (3认同)
  • “Express 将中止当前堆栈并运行所有具有 4 个参数的中间件。” 我想知道 Express 如何能够运行精确的错误处理程序中间件。谢谢! (2认同)

d51*_*512 59

恕我直言,这个问题的接受答案并不准确.正如其他人所说,它实际上是关于控制链中的下一个处理程序何时运行.但是我想提供更多的代码来使它更具体.假设你有这个简单的快递应用:

var express = require('express');
var app = express();

app.get('/user/:id', function (req, res, next) {
    console.log('before request handler');
    next();
});

app.get('/user/:id', function (req, res, next) {
    console.log('handling request');
    res.sendStatus(200);
    next();
});

app.get('/user/:id', function (req, res, next) {
    console.log('after request handler');
    next();
});

app.listen(3000, function () {
    console.log('Example app listening on port 3000!')
});
Run Code Online (Sandbox Code Playgroud)

如果你这样做

curl http://localhost:3000/user/123
Run Code Online (Sandbox Code Playgroud)

你会看到这打印到控制台:

before request handler
handling request
after request handler
Run Code Online (Sandbox Code Playgroud)

现在,如果你next()在中间处理程序中注释掉这样的调用:

app.get('/user/:id', function (req, res, next) {
    console.log('handling request');
    res.sendStatus(200);
    //next();
});
Run Code Online (Sandbox Code Playgroud)

您将在控制台上看到:

before request handler
handling request
Run Code Online (Sandbox Code Playgroud)

请注意,最后一个处理程序(打印的处理程序after request handler)不会运行.那是因为你不再告诉express运行下一个处理程序了.

因此,如果您的"主要"处理程序(返回200的处理程序)成功与否,那么无关紧要,如果您希望其余的中间件运行,则必须调用next().

什么时候会派上用场?假设您要记录进入某个数据库的所有请求,无论请求是否成功.

app.get('/user/:id', function (req, res, next) {
    try {
       // ...
    }
    catch (ex) {
       // ...
    }
    finally {
       // go to the next handler regardless of what happened in this one
       next();
    }
});

app.get('/user/:id', function (req, res, next) {
    logToDatabase(req);
    next();
});
Run Code Online (Sandbox Code Playgroud)

如果要运行第二个处理程序,则必须调用next()第一个处理程序.

请记住,节点是异步的,因此无法知道第一个处理程序的回调何时完成.你必须通过电话告诉它next().

  • 这是一个非常明确的解释.谢谢. (2认同)

Arv*_*ana 11

将正确提到的答案总结在一处,

  • next() :将控制移动到同一路径中的下一个函数。单一路线中具有多种功能的情况。
  • next('route') :通过跳过当前路由中的所有剩余功能,将控制移动到下一个路由。
  • next(err) :将控制移至错误中间件
app.get('/testroute/:id', function (req, res, next) {
  if (req.params.id === '0') next() // Take me to the next function in current route
  else if (req.params.id === '1') next('route') //Take me to next routes/middleware by skipping all other functions in current router  
  else next(new Error('Take me directly to error handler middleware by skipping all other routers/middlewares'))
}, function (req, res, next) {
  // render a regular page
  console.log('Next function in current route')
  res.status(200).send('Next function in current route');
})

// handler for the /testroute/:id path, which renders a special page
app.get('/testroute/:id', function (req, res, next) {
  console.log('Next routes/middleware by skipping all other functions in current router')
  res.status(200).send('Next routes/middleware by skipping all other functions in current router');
}) 
//error middleware
app.use(function (err, req, res, next) {
  console.log('take me to next routes/middleware by skipping all other functions in current router')
  res.status(err.status || 500).send(err.message);
});

Run Code Online (Sandbox Code Playgroud)


kya*_*sar 7

next()without parameter调用框架中的下一个路由处理程序或下一个中间件.

  • 或者下一个中间件. (2认同)