How to handle timeout using request with nodejs

So, I am making this request on the server, and I am setting a timeout, and I want to handle the timeout event, but I also want to handle the "abort" event and be different from one another. I managed to get it done quickly, but I wanted to know if there is a better way to do this. The code looks like this:

makeRequest = function(json, cb){
    var requestError
    request({
        url: REQUEST_URL,
        json: json,
        timeout: 3000,
        headers: {
            'Content-Type': 'application/json'
        }
     }, function(err, res, body){
         if(err) requestError = err
         else cb(null, res, body)
     }).on('abort', function(){
         setTimeout(function({  
             if(requestError != 'ETIMEDOUT') cb(httpStatusCode.REQUEST_TIMEDOUT)
             else cb(httpStatusCode.REQUEST_ABORTED
         }, 1000)
     })
}

      

I noticed that in the timeout event the "abort" event is fired and the request callback is called in that order, so I used the setTimeout function to wait for the request callback and handled the error in the "abort" listener. This seems like a silly way to do it, and I have searched the web and found no way to handle handling only the callback event. I also noticed that the timeout fires the on event. ("Error", function (err) {}) where I can handle this error but also fires the on event. ('Abort', function () {}) and I end up calling the main callback (cb) two times, my application crashing.

Is there a way I can have an event ONLY for the timeout, and one ONLY for the interrupt, so I don't have to use setTimeout?

Or is there any property in my req object that I can check to check if this request has expired or not?

Or do you have any other suggestions for fixing my problem in a less ugly way?

I am using nodejs 0.12.2 and requesting 2.55.0 Thanks!

+3


source to share


1 answer


One of the great things about open source is that you can always just look at a module's code and see how it works.

If you want to get an error, just listen .on('error', function(err) {})

. The error will be reported there. The event .on('abort', function() {})

does not tell you why it was interrupted. But, as you can see from the corresponding source code for the request module, the event is error

always dispatched immediately after the event abort

and it will be e.code

set to ETIMEDOUT

.

Here's a copy of some source code for being .abort()

called where you can see that it fires an error event right away:



  if (self.timeout && !self.timeoutTimer) {
    var timeout = self.timeout < 0 ? 0 : self.timeout
    self.timeoutTimer = setTimeout(function () {
      self.abort()
      var e = new Error('ETIMEDOUT')
      e.code = 'ETIMEDOUT'
      self.emit('error', e)
    }, timeout)

    // Set additional timeout on socket - in case if remote
    // server freeze after sending headers
    if (self.req.setTimeout) { // only works on node 0.6+
      self.req.setTimeout(timeout, function () {
        if (self.req) {
          self.req.abort()
          var e = new Error('ESOCKETTIMEDOUT')
          e.code = 'ESOCKETTIMEDOUT'
          self.emit('error', e)
        }
      })
    }
  }

      

So it seems like you can ignore the event abort

and just listen for the event error

and just call the callback on the event error

.

If your code is such that it gets confusing if the callback is called with an error more than once (which is similar to this), you can change your function makeRequest()

so that it never calls the callback more than once too.

+2


source







All Articles