I love asynchronous programming using promises. Q is my favorite promise implementation library. An asynchronous function can return a promise, and I can setup success and fail callbacks
var q = require('q');
What if we want to automatically fail if
foo takes too long? Q has method
that can reject a promise with a given message
How do I detect if the promise timed out or really failed? I have to check inside the
callback, making the code more complex:
It is very simple to extend or wrap the Q's promise object and extend the
and allow a dedicated callback function on time out, not just an error message. I placed the
code into this gist. The main
feature: we are wrapping the
var _defer = q.defer;
Now we can run the dedicated callback on timed out promises, which gets the original deferred object
- If we reject the promise (line
// 1) we need to make sure the
.failcallback can tell the difference between the timed out and failed promise. For example, by rejecting the promise without arguments in
timeoutand assuming that every true failure would have arguments.
.thenfunction returns a different promise object. We only add the
timeoutmethod to the original promise created in
q.defer(), so if you want a time out, it has to be the first call on the promise.
I extended AngularJs $q promises with timeout method, see this post
Q library has added promise.timeout method that works just like I described above. Any long-running promise can be limited to a given period. If the promise is not resolved after the period expires, the promise is rejected. This allows to start a normal long running action using an ordinary method, but limit it from the outside.
// "normal" promise-returning function, knows nothing about the time limit
This produces the following output
at 10 ms: started long-running promise at 415 ms: promise error with value [Error: timed out] at 1011 ms: resolving long-running promise with 42 after 1 second
While there is a message at
1011 ms before the
deferred.resolve(42); is called, the promise
has already been fulfilled. Thus
onError is not going to be called the second time.
Important notice that the application DOES NOT EXIT until all promises get resolved (after 1 second).
This is the problem with promises - they keep running and there is no way to get them cancelled without
access to the original
var started = +(new Date());