If I create a promise using $interval, it is cancelable See: http://jsbin.com/jeweke/2/
timer = $interval(intervalFunc, intervalDelay, 10);
timer.then(
function(res) {console.log('ok', res);},
function(err) {console.log('err', err);}
);
However, if I chain the promise, the returned promise is not cancelable. See: http://jsbin.com/jeweke/1/
timer = $interval(intervalFunc, intervalDelay, 10)
.then(
function(res) {console.log('ok', res);},
function(err) {console.log('err', err);}
);
What gives? Is this just how it's supposed to work?
Note - the example here is loosely adapted from http://jsfiddle.net/ExpertSystem/fZc3W/
Sometimes in a promise chain, you need to abort the chain and prevent any additional then / catch / finally from running. In simple cases, this can be done by just throwing an exception and catching it at the end of the chain.
Promises have settled (hah) and it appears like it will never be possible to cancel a (pending) promise. Instead, there is a cross-platform (Node, Browsers etc) cancellation primitive as part of WHATWG (a standards body that also builds HTML) called AbortController .
JavaScript Promise Chaining 1 Pending: This state represents either an initial state or fulfilled state or rejected state. 2 Fulfilled: This state represents that the asynchronous operation is successfully completed. 3 Rejected: This state represents that the asynchronous operation is rejected. More ...
Itβs physics. Instead of returning just a Promise, we will also return a cancel callback. Code invoking our Promise-building function can work with the returned promise like normal, but can also invoke the cancel callback in case of timeout, error handling, or user intercession.
(You could also set a cancel method on your Promise before you return it, like promise.cancel = cancel;, but TypeScript/IDE IntelliSense might not be understanding of that approach. Use your judgment.) When building the cancel callback behavior, there are 4 scenarios to consider: cancel is called immediately, before there is anything to clean up.
Promises chaining 1 Returning promises. A handler, used in .then (handler) may create and return a promise. ... 2 Example: loadScript. Here each loadScript call returns a promise, and the next .then runs when it resolves. ... 3 Bigger example: fetch. In frontend programming promises are often used for network requests. ... 4 Summary. ...
That is because the result of promise chain from the $interval
does not have the property which contains the interval id ($$intervalId
). First case you are saving timer promise which has the $intervalId
, in the second case you are saving the promise returned from the chain which is a raw q promise without the $intervalId
property (which is a custom property added on the promise to store the respective setInterval
's id when you call $interval(...
). When you cancel the timer it needs the $intervalId
to cancelInterval and reject the respective timer promise.
This is what interval.cancel
does
interval.cancel = function(promise) {
if (promise && promise.$$intervalId in intervals) {
intervals[promise.$$intervalId].reject('canceled');
clearInterval(promise.$$intervalId);
delete intervals[promise.$$intervalId];
return true;
}
return false;
};
Note the line:-
if (promise && promise.$$intervalId in intervals) {
intervals
are nothing but a map of intervalId and its respective promise (example:- {1:promiseOfInterval1, 2:promiseOfInterval2}
), so without intervalId no cancellation happens. So in short the promise returned by the $interval is q promise plus $intervalId property and when you chain it thorough it is just the $q
implementation which returns back a new deferred object's promise.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With