node如何捕获异常
node基于js的单线程,有了非阻塞异步回调的概念,但是在处理多个并发连接时,并发环境要求高,最重要的是单线程,单核CPU,一个进程crash则web服务都crash,但是为什么node还这么火?甚至有了Node工程师这个岗,肯定就是node有自己crash之前与之后的解决方法,比如捕获异常
问:nodejs如何捕获异常?答:回调函数中有err形参,console.log出来,这是我之前回答别人问题的答案,但是自从我这几天看了如何捕获异常,才知道捕获异常的精髓就是不要让服务crash掉,抛出500状态码。而我回答的是风马牛不相及。
一般如何捕获异常
1、使用uncaughtExprection去捕获异常
process.on("uncaughtExpection",function(err){ console.log(err) })
2、用try-catch在回调函数前捕获异常
var http = require('http'); http.createServer(function(req, res) { try { fn(req, res); } catch(e) { console.log(e.stack); res.end("Error") } }).listen(3000); function fn (req, res) { var name = req.body.name; res.end("回调函数"); };
3、用框架去包住,捕获异常,express做的好
app.use(function(req, res, next) { var err = new Error('Not Found'); err.status = 404; next(err); }); // error handler app.use(function(err, req, res, next) { // set locals, only providing error in development res.locals.message = err.message; res.locals.error = req.app.get('env') === 'development' ? err : {}; // render the error page res.status(err.status || 500); res.render('error'); });
特殊情况如何捕获异常
如果在回调函数中如何捕获异常呢?
如果是回调函数中捕获异常怎么做?用domain去捕获,domian捕获会抛出500错误,但是domain捕获有一个问题,会丢失栈信息,无法保证程序健康进行,所以要结束进程,在回调函数中process.exit(1)
,然后用node的server.close方法再去释放,server.close连接释放后自动结束进程,所以不用在server.close中去结束进程process.exit(1)
uncaughtExpection捕获异常的的原理就是:uncaughtExpection事件存在回调函数process.on("uncaughtExpection",callback)
时node不会强制结束进程,这样可弥补domain丢失stack的问题
所以domian去捕获绝大部分回调函数中的异常,uncaughtExpection去捕获丢失stack异常,这样就完整了
uncaughtExprection+domain去捕获回调函数中的异常就ok
app.use(function(req,res,next){ var reqDomain = domain.create(); reqDomain.on("err",function(){ try { var killTimer = setTimeout(function(){ process.exit(1); },1000) killTimer.unref(); server.close(); res.send(500); } catch(e) { // statements console.log(e.stack); } }) reqDomain.run(next); }); process.on("uncaughtException",function(err){ console.log(err); try{ var killTimer = setTimeout(function(){ process.exit(1) },1000) killTimer.unref(); server.close(); }catch(e){ console.log(e.stack); } });
express特点
express的优点
1、对node的HTTP封装好了,直接去app.listen
2、中间件完成了post/get请求,回调函数中有req,res,next,其中next的作用就是把请求传递给下一个中间件,比如两次使用use中间件去处理同一请求,用next传递可以同时处理
3、对post封装的很好,post中node中是这样写的
function onRequest(req,res){ req.addListener("data",function(postdata){ //data }) req.addListener("end",function(){ //router }) }
实现post请求需要监听两次事件:"data"、"end"。先执行data事件,data事件接收数据块,接收完毕且成功,再触发一次end事件,将post的数据返还给路由
而app.post就完成了,最多需要设定
app.use(bodyParser.json()); app.use(bodyParser.urlencoded({ extended: false }));
用于接收post请求的参数
4、内置路由,提高了代码复用率
app.use('/', index);
5、node没有web容器的概念,express有设置了静态文件夹
app.use(express.static(path.join(__dirname, 'public')));
6、设置了ejs/jade模版引擎
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
7、对cookie、mongoDB等操作良好
8、npm、require包或文件非常方便
etc...
express缺点
与express框架同一个类型的有koa hapi 等,没用过后两个,不好评价
据说一个尴尬的缺点,一个问题express有多个操纵方法
还有一个,回调函数中嵌套回调函数,容易引用错误的变量,或者无意中改了外部变量
了解更多点这里
其实node如何捕获异常和express的特点,这两个问题是电面蚂蚁金服问的问题,我回答的不好,所以连夜回顾,整体,分析,总结
好了,今天的进阶完毕,下次更新就是分析js所有的异步操作,包括ES6的Promise和ES7的async/await,晚安