javascript – 如何使用nodejs请求处理超时

所以,我正在向服务器发出这个请求,我设置了一个超时,我想处理超时事件,但我也想处理’abort’事件并且彼此不同.我设法快速解决了这个问题,但我想知道是否有更好的方法来做到这一点.代码如下所示:

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)
     })
}

我注意到在超时事件中,’abort’事件都被触发,并且按顺序调用请求回调,所以我使用setTimeout函数等待请求回调,而不是处理’abort’监听器中的错误.这似乎是一种愚蠢的方式,我在网上搜索并没有找到办法只处理回调事件.我还注意到超时触发了on.(‘error’,function(err){})事件,我可以处理错误,但它也调用on.(‘abort’,function(){})事件我最终调用了两次主回调(cb),崩溃了我的应用程序.

有没有办法我只能为超时发一个事件,而且只有一个中止,所以我不必使用setTimeout?

或者我的req对象中是否有任何属性可以检查该请求是否超时?

或者您是否有其他建议以不那么丑陋的方式解决我的问题?

我正在使用nodejs 0.12.2并请求2.55.0
谢谢!

最佳答案 关于开源的一个好处是你可以随时查看模块的代码并查看它是如何工作的.

如果你想要错误,那就听一下.on(‘error’,function(err){}).错误将在那里传递. .on(‘abort’,function(){})事件不会告诉您为什么它被中止.但是,正如您在relevant source code中可以看到的请求模块一样,错误事件总是在中止事件之后立即发送,它将e.code设置为ETIMEDOUT.

以下是调用.abort()时的一些相关源代码的副本,您可以看到它在之后触发错误事件:

  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)
        }
      })
    }
  }

所以,似乎你可以忽略中止事件,只是监听错误事件,只是在错误事件上调用你的回调.

如果你的代码是这样的,如果回调被多次调用错误(听起来像是这样),那么你可以改变你的makeRequest()函数,这样它就不会多次调用回调函数.

点赞