2014-10-03 43 views
6

我試圖在超時或錯誤時自動重試HTTP請求。
目前我的代碼看起來是這樣的:Nodejs http在超時或錯誤時重試

var req = http.get(url, doStuff) 
       .on('error', retry) 
       .setTimeout(10000, retry); 

然而,單個請求有時可以同時觸發「上的錯誤」和「超時」事件。什麼是更好的實施重試的方式?

回答

4

你可以嘗試這樣的事:

function doRequest(url, callback) { 
    var timer, 
     req, 
     sawResponse = false; 
    req = http.get(url, callback) 
      .on('error', function(err) { 
       clearTimeout(timer); 
       req.abort(); 
       // prevent multiple execution of `callback` if error after 
       // response 
       if (!sawResponse) 
       doRequest(url, callback); 
      }).on('socket', function(sock) { 
       timer = setTimeout(function() { 
       req.abort(); 
       doRequest(url, callback); 
       }, 10000); 
      }).once('response', function(res) { 
       sawResponse = true; 
       clearTimeout(timer); 
      }); 
} 

UPDATE:在節點的最近/現代版本,您現在可以指定一個timeout選項(以毫秒計),其設置套接字超時(前插座已連接)。例如:

http.get({ 
host: 'example.org', 
path: '/foo', 
timeout: 5000 
}, (res) => { 
    // ... 
}); 
1

這是我工作的代碼。關鍵是在超時後銷燬套接字以及檢查響應是否完成。

function httpGet(url, callback) { 
    var retry = function(e) { 
     console.log("Got error: " + e.message); 
     httpGet(url, callback); //retry 
    } 

    var req = http.get(url, function(res) { 
     var body = new Buffer(0); 
     res.on('data', function (chunk) { 
      body = Buffer.concat([body, chunk]); 
     }); 
     res.on('end', function() { 
      if(this.complete) callback(body); 
      else retry({message: "Incomplete response"}); 
     }); 
    }).on('error', retry) 
    .setTimeout(20000, function(thing){ 
     this.socket.destroy(); 
    }); 
} 
7

我在找同樣的東西,發現有趣的模塊requestretry,非常適合這樣的要求。

下面是用法:

var request = require('requestretry') 

request({ 
    url: myURL, 
    json: true, 
    maxAttempts: 5, // (default) try 5 times 
    retryDelay: 5000, // (default) wait for 5s before trying again 
    retrySrategy: request.RetryStrategies.HTTPOrNetworkError // (default) retry on 5xx or network errors 
}, function(err, response, body){ 
    // this callback will only be called when the request succeeded or after maxAttempts or on error 
    if (response) { 
    console.log('The number of request attempts: ' + response.attempts); 
    } 
}) 
+0

爲什麼這個downvoted,我不知道? – Holf 2016-12-16 13:57:23

+1

@Holf不知道,我只是回答,因爲我認爲這個模塊是針對問題提到的問題的完美解決方案。我使用了模塊,它工作得很好。 – Gagan 2016-12-21 09:14:26

+0

是的,我也發現它是完美的解決方案。 – Holf 2016-12-21 10:03:04