1

Is there any way in Node.js to kill an async operation and preventing it from completing (calling callbacks, or resolving promise) ?

To be more specific, let's say I did an http.get() call. It is an async operation that eventually will call the callback passed, or fire an error event. But it takes too long and the logic in my code could say "hey, I have been waiting for so long, I don't want to wait any longer!" and do something else instead. The problem is, the callback will eventually be called, and that might mess up stuff! So yeah, is there a way to stop that callback from being executed? My idea was:

var notWaitingAnyMore = false;
http.get({}, function(res) {
    if(notWaitingAnyMore) { // do stuff! }
});
//do some other stuff
//now fed up with waiting:
notWaitingAnyMore = true;

But this doesn't seem like a nice solution to me...

simbabque
  • 53,749
  • 8
  • 73
  • 136
Daniel Gruszczyk
  • 5,379
  • 8
  • 47
  • 86
  • Make this use promises. Then, shove in an intermediate promise that also completes when notWaitingAnyMore becomes true and throws away the http result. – usr Jul 06 '15 at 15:51
  • Is this what you're looking for http://stackoverflow.com/a/8377810/57095 ? – Alberto Zaccagni Jul 06 '15 at 15:51
  • Do you want to set a [timeout on an `http` call](http://stackoverflow.com/questions/6214902/how-to-set-a-timeout-on-a-http-request-in-node)? It's worth noting that many JavaScript Promise libraries support native timeouts that handle this for you automatically. – tadman Jul 06 '15 at 15:51
  • No, http.get() is an example, it could be a DB call, or any async operation for that matter – Daniel Gruszczyk Jul 06 '15 at 15:54
  • This is possible only if the API provides a mechanism for it (like `clearTimeout` does for `setTimeout`). Otherwise, you'll simply need to have your callback aware of the possibility that it may need to do nothing, as you've shown in your example. I think Promises are probably an idiomatic way to do this, as others have already suggested. – apsillers Jul 06 '15 at 15:54
  • Your question implies that you're setting `notWaitingAnyMore` to `true` synchronously. Is that true? If so, your calls will always time out. – Aaron Dufour Jul 07 '15 at 03:12

2 Answers2

1

Your best bet is probably to use promises. For example, if you are using bluebird, this problem is very easily solved:

new Promise(function(resolve, reject) {
  http.get({}, resolve);
}).timeout(500) // timeout length in ms
.then(function(res) {
  // do stuff!
}).catch(Promise.TimeoutError, function(err) {
  // do you need to do something after it times out?
})
//do some other stuff
Aaron Dufour
  • 17,288
  • 1
  • 47
  • 69
0

You're super close

function outerMethod(input, callback){
  var notWaitingAnyMore = false;
  var maxTimeout = 1000*60; // 1min
  http.get({}, function(res) {
    if(!notWaitingAnyMore) {
      // do stuff!
      notWaitingAnyMore = true;
      callback(null, res);
    } else {
      return;
    }
  });
  setTimeout(function(){
    // We want to avoid calling back a second time if the http callback ran first:
    if(!notWaitingAnyMore) {
      notWaitingAnyMore = true;
      callback('timeout');
    } else {
      return
    }
  }, maxTimeout)
};
Plato
  • 10,812
  • 2
  • 41
  • 61