当前位置: 首页 > 后端技术 > Node.js

Express文档(错误处理)

时间:2023-04-04 01:30:30 Node.js

ErrorHandling错误处理是指Express如何捕获和处理同步和异步发生的错误。Express带有默认的错误处理程序,因此您无需编写自己的错误处理程序即可开始使用。捕获错误确保Express捕获运行路由处理程序和中间件时发生的所有错误非常重要。路由处理程序和中间件内部的同步代码中发生的错误不需要额外的工作,如果同步代码抛出错误,Express将捕获并处理它,例如:app.get("/",function(req,res){thrownewError("BROKEN");//Express会自己捕获它。});对于路由处理程序和中间件调用的异步函数返回的错误,它们必须传递给next()函数,Express将捕获并处理它们,例如:app.get("/",function(req,res,next){fs.readFile("/file-does-not-exist",function(err,data){if(err){next(err);//将错误传递给Express。}else{res.send(data);}});});如果有任何东西传递给next()函数(字符串'route'除外),Express会将当前请求视为错误,并将跳过任何剩余的非错误处理路由和中间件函数。如果序列中的回调不提供数据,只提供错误,你可以简化这段代码如下:app.get("/",[function(req,res,next){fs.writeFile("/inaccessible-path","data",next);},function(req,res){res.send("OK");}]);在上面的示例中,next作为fs.writeFile的回调提供,调用时有无错误,如果没有错误,则执行第二个处理程序,否则Express会捕获并处理错误。你必须捕获路由处理程序或中间件调用的异步代码中发生的错误,并将它们传递给Express进行处理,例如:app.get("/",function(req,res,next){setTimeout(function(){try{thrownewError("BROKEN");}catch(err){next(err);}},100);});上面的示例使用try...catch块来捕获错误并将它们传递给Express,如果省略try...catch块,Express将不会捕获错误,因为它不是同步处理程序代码的一部分。使用承诺来避免try...catch块的开销或使用返回承诺的函数,例如:app.get("/",function(req,res,next){Promise.resolve().then(function(){thrownewError("BROKEN");}).catch(next);//错误将传递给Express。});由于promises会自动捕获同步错误并拒绝promises,您可以简单地提供next作为最终的catch处理程序,Express将捕获错误,因为catch处理程序将错误作为第一个参数。您还可以使用处理程序链来依赖同步错误捕获,方法是将异步代码简化为类似以下的简单代码:app.get("/",[function(req,res,next){fs.readFile("/maybe-valid-file","utf8",function(err,data){res.locals.data=data;next(err);});},function(req,res){res.locals.data=res.locals.data.split(",")[1];res.send(res.locals.data);}]);上面的例子有一些来自readFile调用的简单语句,如果readFile导致错误,那么它会将错误传递给Express,否则你很快就会回到链中下一个处理程序中的同步错误处理世界。上面的示例然后尝试处理数据,如果失败,同步错误处理程序将捕获它,如果您在readFile回调中完成此处理,应用程序可能会退出并且Express错误处理程序将不会运行。无论您使用哪种方法,如果您想要调用Express错误处理程序并保持应用程序处于活动状态,则必须确保Express收到错误。DefaultErrorHandlerExpress带有一个内置的错误处理程序,可以处理应用程序中可能遇到的任何错误,这个默认的错误处理中间件函数添加在中间件函数堆栈的末尾。如果你将错误传递给next()而你没有在自定义错误处理程序中处理它,它将由内置错误处理程序处理,错误将向客户端写入堆栈跟踪,堆栈跟踪不是包括在生产中。将环境变量NODE_ENV设置为production以在生产模式下运行应用程序。如果在开始写入响应后调用next()并发生错误(例如,如果在将响应流式传输到客户端时遇到错误),Express默认错误处理程序将关闭连接并使请求失败。因此,当您添加自定义错误处理程序时,当标头已发送到客户端时,您必须委托给默认的Express错误处理程序:functionerrorHandler(err,req,res,next){if(res.headersSent){returnnext(err)}res.status(500)res.render('error',{error:err})}注意,如果你在代码中多次调用next()出错,默认的错误处理将被触发程序,即使自定义错误处理中间件已到位。编写错误处理程序以与其他中间件函数相同的方式定义错误处理中间件函数,除了错误处理函数有四个参数而不是三个:(err,req,res,next),例如:app.use(function(err,req,res,next){console.error(err.stack)res.status(500).send('Somethingbroke!')})您可以在其他app.use()和路由调用Handle中间件之后定义错误,例如:varbodyParser=require('body-parser')varmethodOverride=require('method-override')app.use(bodyParser.urlencoded({extended:true}))app.use(bodyParser.json())app.use(methodOverride())app.use(function(err,req,res,next){//logic})中间件函数内的响应可以是任何格式,例如HTML错误页面、简单消息或JSON字符串。出于组织(和更高级别的框架)的目的,您可以定义多个错误处理中间件功能,就像您使用常规中间件功能一样,例如为使用和不使用XHR的请求定义错误处理程序:(bodyParser.json())app.use(methodOverride())app.use(logErrors)app.use(clientErrorHandler)app.use(errorHandler)在此示例中,通用logErrors可能会将请求和错误消息写入stderr,例如:functionlogErrors(err,req,res,next){console.error(err.stack)next(err)}同样在这个例子中,clientErrorHandler定义如下,在这种情况下,错误被显式传递给下一个错误。请注意,当您不在错误处理函数中调用“next”时,您有责任编写(并完成)响应,否则请求将“挂起”并且不符合垃圾收集的条件。functionclientErrorHandler(err,req,res,next){if(req.xhr){res.status(500).send({error:'Somethingfailed!'})}else{next(err)}}实现“catch-all"用于errorHandler函数,像这样(例如):functionerrorHandler(err,req,res,next){res.status(500)res.render('error',{error:err})}如果你have一个带有多个回调函数的routehandler,可以通过route参数跳转到下一个routehandler,例如:app.get('/a_route_behind_paywall',functioncheckIfPaidSubscriber(req,res,next){if(!req.user.hasPaid){//继续处理这个请求next('route')}else{next();}},functiongetPaidContent(req,res,next){PaidContent.find(function(err,doc){if(err)returnnext(err)res.json(doc)})})在此示例中,将跳过getPaidContent处理程序,但应用程序中/a_route_behind_paywall中的任何剩余处理程序将继续执行。对next()和next(err)的调用表明当前处理程序已完成以及它处于什么状态,next(err)将跳过链中所有剩余的处理程序,除了那些设置为处理错误的如上所述。上一篇:使用模板引擎下一篇:调试