14

This is the code which I have been using to download images from URLs:

http.get(options, function (res) {
    res.on('data', function (data) {
        file.write(data);
    }).on('end', function () {
        file.end();
        console.log(file_name + ' downloaded ');
        cb(null, file.path);
    }).on('error', function (err) {
        console.log("Got error: " + err.message);
        cb(err, null);
    });
});

How can I add a timeout for every request so that it doesn't stay on waiting for a response which is either large data or unresponsive?

honk
  • 9,137
  • 11
  • 75
  • 83
user1386776
  • 395
  • 3
  • 8
  • 13

1 Answers1

35

OK, there are at least two solutions to your problem. An easy one:

var request = http.get(options, function (res) {
    // other code goes here
});
request.setTimeout( 10000, function( ) {
    // handle timeout here
});

but might not be flexible enough. The more advanced one:

var timeout_wrapper = function( req ) {
    return function( ) {
        // do some logging, cleaning, etc. depending on req
        req.abort( );
    };
};

var request = http.get(options, function (res) {
    res.on('data', function (data) {
        file.write(data);
        // reset timeout
        clearTimeout( timeout );
        timeout = setTimeout( fn, 10000 );
    }).on('end', function () {
        // clear timeout
        clearTimeout( timeout );
        file.end();
        console.log(file_name + ' downloaded ');
        cb(null, file.path);
    }).on('error', function (err) {
        // clear timeout
        clearTimeout( timeout );
        console.log("Got error: " + err.message);
        cb(err, null);
    });
});

// generate timeout handler
var fn = timeout_wrapper( request );

// set initial timeout
var timeout = setTimeout( fn, 10000 );
freakish
  • 54,167
  • 9
  • 132
  • 169
  • You have a mistake in your advanced version of code: initial timeout setting `var timeout = setTimeout( fn, 10000 );` should be outside of the `http.get` callback. – zavg May 22 '13 at 16:38
  • 6
    What are the limitations of the first method? – Robotbugs May 24 '13 at 22:05
  • @Robotbugs Sorry, I didn't see your comment for sooo long. Asnwering the question: for example you might want to alter timeout depending on whether you've received data or not. So for example after receiving any piece of data you extend the timeout. Unlikely that anyone would do that but still possible. :) – freakish Jan 19 '14 at 19:52
  • @freakish: Hi, although it's been more than one year, your answer is really helpful for me. However, there is still a problem I cannot figure it out by myself. This is my example http://jsfiddle.net/oe6freko/ . I want the callback of req.setTimeout not to be called after the callback of http.get is called. In my example, when I deal with huge amount of requests, some time it still print out `req.abort is still excuted AFTER response is returned in callback function`. Can you help me out in this case? Thanks in advances. – Mr Cold Aug 23 '15 at 05:28
  • @MrCold , Is that an issue? My understanding is that its a valid usecase, for eg. you might receive a 200 response right away but the data in response is so huge that socketTimeout expires, while reading it. A strange case might be to have the timeout fired along with 'end'. – Saumitra R. Bhave Mar 07 '17 at 12:21