• node 进阶 | 通过node中如何捕获异常阐述express的特点


    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,晚安

      

  • 相关阅读:
    Mysql登录错误:ERROR 1045 (28000): Plugin caching_sha2_password could not be loaded
    Docker配置LNMP环境
    Docker安装mysqli扩展和gd扩展
    Docker常用命令
    Ubuntu常用命令
    单例模式的优缺点和使用场景
    ABP 多租户数据共享
    ABP Core 后台Angular+Ng-Zorro 图片上传
    ERROR Error: If ngModel is used within a form tag, either the name attribute must be set or the form control must be defined as 'standalone' in ngModelOptions.
    AbpCore 执行迁移文件生成数据库报错 Could not find root folder of the web project!
  • 原文地址:https://www.cnblogs.com/dirkhe/p/7368357.html
Copyright © 2020-2023  润新知