【问题标题】:How to handle timeout using request with nodejs如何使用 nodejs 请求处理超时
【发布时间】:2015-09-24 07:48:21
【问题描述】:

所以,我正在向服务器发出这个请求,我设置了一个超时,我想处理超时事件,但我也想处理“中止”事件,并且彼此不同。我设法通过快速修复来做到这一点,但我想知道是否有更好的方法来做到这一点。代码如下所示:

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

我注意到在超时事件中触发了“中止”事件并按此顺序调用请求回调,因此我使用 setTimeout 函数等待请求回调,然后处理“中止”中的错误'听众。这似乎是一种愚蠢的方法,我在网上搜索并没有找到只处理回调事件的方法。我还注意到超时触发了 on.('error', function(err){}) 事件,我可以在其中处理错误,但它也调用 on.('abort', function(){}) 事件我最终调用了主回调 (cb) 两次,导致我的应用程序崩溃。

有没有一种方法可以让我只为超时设置一个事件,而为一个中止设置一个事件,这样我就不必使用 setTimeout?

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

或者您有什么其他建议可以以一种不那么难看的方式解决我的问题吗?

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

【问题讨论】:

  • 如果我错了请纠正我,但不是因为超时而中止吗?

标签: javascript node.js request timeout


【解决方案1】:

开源的一大优点是您可以随时查看模块的代码并了解它是如何工作的。

如果你想知道错误,那么只需收听.on('error', function(err) {})。错误将在那里传递。 .on('abort', function() {}) 事件不会告诉您它被中止的原因。但是,从请求模块的relevant source code 可以看出,error 事件总是在abort 事件之后立即发送,并且它会将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)
        }
      })
    }
  }

因此,您似乎可以忽略 abort 事件,只监听 error 事件,然后在 error 事件上调用您的回调。

如果您的代码在多次调用回调时出现错误(听起来确实如此)时会出现混乱,那么您可以更改 makeRequest() 函数,使其调用回调的次数不超过也有一次。

【讨论】:

    猜你喜欢
    • 2012-10-30
    • 1970-01-01
    • 1970-01-01
    • 2011-04-17
    • 1970-01-01
    • 1970-01-01
    • 2016-02-06
    • 2017-09-03
    相关资源
    最近更新 更多