表示下一个函数,它到底是用来做什么的?

一直试图找到一个很好的描述什么 next()方法做。在 Express 文档中说,可以使用 next('route')跳转到该路由,并跳过其间的所有路由,但有时调用 next时没有参数。有人知道描述 next函数的教程吗?

88273 次浏览

没有参数的 next()表示“开玩笑的,我实际上并不想处理这个问题”。它回到里面,试图找到下一条匹配的路线。

这是非常有用的,比如说,如果您希望使用某种带有 url 蛞蝓的页面管理器,以及许多其他东西,但这里有一个示例。

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() {
//...
});

编写的代码应该在数据库中检查具有某个 id 蛞蝓的页面。如果它找到一个,就把它放倒!如果找不到,那么忽略这个路由处理程序并检查其他路由处理程序。

所以没有参数的 next()允许假装你没有处理路由,这样别的东西就可以把它捡起来。


或者一个 app.all('*')的命中计数器。它允许您执行一些共享的设置代码,然后转移到其他路由来执行更具体的操作。

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


app.get('/other_routes', function() {
//...
});

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

function (<err>, req, res, next) {}

Js 应用程序是这些函数的堆栈。

enter image description here

路由器是特殊的,它的中间件,让您执行一个或多个中间件的某个网址。所以这是一个堆栈中的一个堆栈。

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

function (err, req, res, next) {}

这个中间件用于处理任何错误:

next({ type: 'database', error: 'datacenter blew up' });

有了这个错误,我可能会告诉用户有什么地方出错了,并记录真正的错误。

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

如果您将 Express.js 应用程序想象成一个堆栈,那么您自己可能就能够解决许多奇怪的问题。例如,当你在路由器之后添加 Cookie 中间件时,你的路由器就不会有 Cookie 了。

医生

您定义错误处理中间件的方式与其他中间件相同,只不过使用了四个参数而不是三个; 特别是使用了签名(err,req,res,next) :

app.use(function (err, req, res, next) {
console.error(err.stack)
res.status(500).send('Something broke!')
})

Next ()在没有参数的情况下调用框架中的下一个路由处理程序或下一个中间件。

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

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!')
});

如果你愿意的话

curl http://localhost:3000/user/123

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

before request handler
handling request
after request handler

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

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

您将在控制台上看到以下内容:

before request handler
handling request

注意,最后一个处理程序(打印 after request handler的处理程序)不运行。这是因为您不再告诉 Express 运行下一个处理程序。

所以不管你的“ main”处理程序(返回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();
});

如果希望运行第二个处理程序,则必须在第一个处理程序中调用 next()

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

问题还问及使用下一个(’路线’) ,似乎涵盖了一周的提供的答案,迄今为止:

  1. Next ()的用法:

简而言之: 下一个中间件功能。

从这个官方 Express JS 文档-“ write-midware”页面摘录:

中间件函数 myLogger 只是打印一条消息,然后通过调用 next ()函数将请求传递给堆栈中的 下一个中间件功能

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


var myLogger = function (req, res, next) {
console.log('LOGGED')
next()
}


app.use(myLogger)


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


app.listen(3000)

Express JS 文档的这一页 声明“如果当前中间件函数没有结束请求-响应周期,它必须调用 next ()将控制传递给下一个中间件函数。否则,请求将被搁置。”

  1. 下一站(「路线」)的用法:

简而言之: 下一条路(相对于 next ()情况下的 下一个中间件功能)

摘录自 Express JS 文档-“ using-midware”页面:

”要跳过路由器中间件堆栈中其余的中间件函数,请调用 next (‘ path’)将控制权传递给 下一条路。注意: next (‘ path’)将仅在使用 app.Method ()或 router.Method ()函数加载的中间件函数中工作。

这个例子展示了一个中间件子堆栈,它处理对/user/: id 路径的 GET 请求。”

app.get('/user/:id', function (req, res, next) {
// if the user ID is 0, skip to the next route
if (req.params.id === '0') next('route')
// otherwise pass the control to the next middleware function in this stack
else next()
}, function (req, res, next) {
// render a regular page
res.render('regular')
})


// handler for the /user/:id path, which renders a special page
app.get('/user/:id', function (req, res, next) {
res.render('special')
})

它仅仅意味着将控制传递给下一个处理程序。

干杯

注意上面对 next ()的调用。调用此函数将调用应用程序中的下一个中间件函数。Next ()函数不是 Node.js 或 Express API 的一部分,而是传递给中间件函数的第三个参数。Next ()函数可以命名任何东西,但是按照惯例,它总是被命名为“ next”。为了避免混淆,总是使用这个约定。

Next () 是带有 req 的中间件函数的回调参数,res 是下面代码中的 next 的 http 请求和响应参数。

Get (’/’,(req,res,next) = > { next ()}) ;

因此 next ()调用传入的中间件函数。如果当前中间件函数没有结束请求-响应周期,它应该调用 next () ,否则请求将被挂起并超时。

当多个中间件函数被传递给 应用程式或应用程序时,next () fn 需要在每个中间件函数中被调用。方法,否则不会调用下一个中间件函数(如果传递了多于一个中间件函数)。若要跳过调用其余中间件函数,请在中间件函数中调用 下一页(「路线」),在此之后不应调用其他中间件函数。在下面的代码中,fn1将被调用,fn2也将被调用,因为 next ()在 fn1中被调用。但是,fn3不会被调用,因为 next (‘ path’)是在 fn2中调用的。

app.get('/fetch', function fn1(req, res, next)  {
console.log("First middleware function called");
next();
},
function fn2(req, res, next) {
console.log("Second middleware function called");
next("route");
},
function fn3(req, res, next) {
console.log("Third middleware function will not be called");
next();
})

在一个地方总结正确提到的答案,

  • Next () : 将控件移动到同一路由中的下一个函数 单一路线中的多重功能。
  • 下一个(“路线”) : 跳过所有剩余的路线,将控制移动到下一个路线 在当前路线中起作用。
  • 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);
});