美文网首页雕bug小技程序员今日看点
如何捕捉request抛出的异常

如何捕捉request抛出的异常

作者: Liutos | 来源:发表于2017-01-08 22:21 被阅读1000次

    request是用Node.js编写的一个HTTP客户端库,用于发出HTTP/HTTPS协议的请求,项目主页在此。它提供回调风格的API,例如下面的代码将访问example.com并将页面源码输出到终端

    'use strict';
    
    const request = require('request');
    
    request('http://example.com/', function (error, response, body) {
      if (error) {
        console.error(error);
      } else {
        console.log(body);
      }
    });
    

    保存到文件request-example.js中,在命令行执行下列代码即可看到效果

    node request-example.js
    

    除了网页之外,request当然也可以请求HTTP协议的服务端API。但如果只是想要请求一下接口,而不需要获得响应结果时,可能会写出下面这样的代码

    'use strict';
    
    const request = require('request');
    
    request('http://example.com/');
    

    这样确实可以对服务端API发出请求,可以在本地启动一个Web服务器验证这一点,例如使用下列命令

    python -m SimpleHTTPServer 8000
    

    就可以启动一个监听8000端口的HTTP服务器了。将request-example.js文件中的目标地址改为http://127.0.0.1:8000/后再执行,就可以看到Web服务器在终端输出了一行访问日志。

    可如果请求服务端API的过程中遇到了问题,上面的代码将会怎样呢?我最开始认为,既然回调函数的第一个参数是用于接收可能出现的错误的,那么如果没有回调函数,这个错误无处可去,这个它应该会被安静地丢掉。为了验证这个猜想,我把将本地的Web服务器关闭,然后再执行这段Node.js代码,结果在我的电脑上,node输出了如下信息

    events.js:160
          throw er; // Unhandled 'error' event
          ^
    
    Error: connect ECONNREFUSED 127.0.0.1:8000
        at Object.exports._errnoException (util.js:1022:11)
        at exports._exceptionWithHostPort (util.js:1045:20)
        at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1087:14)
    

    出乎意料,request居然抛出了异常,这是为什么呢?阅读request的源代码后发现,如果调用request时提供了回调函数,那么下面这段代码会使用这个回调函数来处理error事件

      if (!self._callback && self.callback) {
        self._callback = self.callback
        self.callback = function () {
          if (self._callbackCalled) {
            return // Print a warning maybe?
          }
          self._callbackCalled = true
          self._callback.apply(self, arguments)
        }
        self.on('error', self.callback.bind()) // <-- 就是这一句
        self.on('complete', self.callback.bind(self, null))
      }
    

    而如果没有传入回调函数,那么当请求对象(self.req)收到error事件时,会调用onRequestError方法,并在Request对象上主动发送'error'事件。由于没有处理'error'事件的回调函数,因此在onRequestError方法中抛出的错误,将会成为一个'uncaughtException',一直抛出到node进程这一级(因为对node的事件机制不是很清楚,这一部分只是我的猜测)。如果没有对'uncaughtException'事件进行处理,node进程就会被终止并输出上文所看到的错误信息。

    因此,如果要在不传递回调函数的情况下忽略可能发生的网络错误,应当使用下面的代码

    'use strict';
    
    const request = require('request');
    
    process.on('uncaughtException', function (error) {
      console.error('catch uncaughtException', error);
    });
    
    request('http://127.0.0.1:8000/');
    

    老实说,上面的代码还不如写成

    'use strict';
    
    const request = require('request');
    
    request('http://127.0.0.1:8000/', function (error) {
      console.error(error);
    });
    

    我的目的只在于请求服务端API而不在意失败,因此最终的代码如下

    'use strict';
    
    const request = require('request');
    
    request('http://127.0.0.1:8000/', function () {});
    

    相关文章

      网友评论

        本文标题:如何捕捉request抛出的异常

        本文链接:https://www.haomeiwen.com/subject/froqbttx.html