Skip to content
This repository has been archived by the owner on Apr 12, 2024. It is now read-only.

fix($timeout/$interval): throw when trying to cancel non-$timeout/$interval promise #16476

Closed
wants to merge 4 commits into from

Conversation

gkalpak
Copy link
Member

@gkalpak gkalpak commented Mar 5, 2018

What kind of change does this PR introduce? (Bug fix, feature, docs update, ...)
Bug fix (sort of).

What is the current behavior? (You can also link to an open issue here)
Calling $timeout/$interval.cancel() with a non-$timeout/$interval promise silently does nothing.
This can for example happen, when calling .then()/.catch() on the returned promise, which creates a new promise and use that new promise for cancelling.

What is the new behavior (if this is a feature change)?
Passing a non-$timeout/$interval promise to $timeout/$interval.cancel() throws an error.
This will help catching issues tht would otherwise go unnoticed.

Does this PR introduce a breaking change?
Yes.

Please check if the PR fulfills these requirements

  • The commit message follows our guidelines
  • Fix/Feature: Docs have been added/updated
  • Fix/Feature: Tests have been added; existing tests pass

Other information:
Fixes #16424.

Copy link
Member

@mgol mgol left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Maybe you could land the big indentation change in src/ng/interval.js separately but no biggie.

Copy link
Contributor

@Narretz Narretz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd also like to see the indentation changes in a separate commit :>

Previously, calling `$timeout.cancel()` with a promise that was not
generated by a call to `$timeout()` would do nothing. This could, for
example, happen when calling `.then()`/`.catch()` on the returned
promise, which creates a new promise, and passing that to
`$timeout.cancel()`.
With this commit, `$timeout.cancel()` will throw an error if called with
a non-$timeout promise, thus surfacing errors that would otherwise go
unnoticed.

Fixes angular#16424

BREAKING CHNAGE:

`$timeout.cancel()` will throw an error if called with a promise that
was not generated by `$timeout()`. Previously, it would silently do
nothing.

Before:
```js
var promise = $timeout(doSomething, 1000).then(doSomethingElse);
$timeout.cancel(promise);  // No error; timeout NOT canceled.
```

After:
```js
var promise = $timeout(doSomething, 1000).then(doSomethingElse);
$timeout.cancel(promise);  // Throws error.
```

Correct usage:
```js
var promise = $timeout(doSomething, 1000);
var newPromise = promise.then(doSomethingElse);
$timeout.cancel(promise);  // Timeout canceled.
```
Previously, calling `$interval.cancel()` with a promise that was not
generated by a call to `$interval()` would do nothing. This could, for
example, happen when calling `.then()`/`.catch()` on the returned
promise, which creates a new promise, and passing that to
`$interval.cancel()`.
With this commit, `$interval.cancel()` will throw an error if called
with a non-$interval promise, thus surfacing errors that would otherwise
go unnoticed.

Related to angular#16424.

BREAKING CHNAGE:

`$interval.cancel()` will throw an error if called with a promise that
was not generated by `$interval()`. Previously, it would silently do
nothing.

Before:
```js
var promise = $interval(doSomething, 1000, 5).then(doSomethingElse);
$interval.cancel(promise);  // No error; interval NOT canceled.
```

After:
```js
var promise = $interval(doSomething, 1000, 5).then(doSomethingElse);
$interval.cancel(promise);  // Throws error.
```

Correct usage:
```js
var promise = $interval(doSomething, 1000, 5);
var newPromise = promise.then(doSomethingElse);
$interval.cancel(promise);  // Interval canceled.
```
@gkalpak gkalpak force-pushed the fix-timeout-throw-on-cancel branch from 3cb3ac0 to 7867a94 Compare March 13, 2018 17:54
@gkalpak
Copy link
Member Author

gkalpak commented Mar 13, 2018

Moved indentation fixes to separate commits.

@gkalpak gkalpak closed this in a8bef95 Mar 13, 2018
@gkalpak gkalpak deleted the fix-timeout-throw-on-cancel branch March 13, 2018 19:26
@abobwhite
Copy link

Thanks for getting on this so quickly. I have a unit test in my app to prevent this in the future but certainly helps to have an exception safeguard!

gkalpak added a commit to gkalpak/angular.js that referenced this pull request May 5, 2018
gkalpak added a commit that referenced this pull request May 5, 2018
gkalpak added a commit to gkalpak/angular.js that referenced this pull request May 5, 2018
gkalpak added a commit that referenced this pull request May 5, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Promise returned from $timeout should not be chained because $$timeoutId is lost
5 participants