Skip to content
This repository has been archived by the owner on May 29, 2019. It is now read-only.

fix(carousel): using setInterval to get rid of dangling $timeouts #1423

Closed
wants to merge 2 commits into from

Conversation

joshkurz
Copy link
Contributor

There are a couple issues with how the carousel currently handles its interval functionality.

  1. When Angular runs its digest loop, two $timeouts are set each iteration. These timeouts are not clearing correctly on the browser window. During the digest iterations, currentTimeout is being overwritten multiple times and its relevant timeout promise object is lost in the carousel's controller context. Normally this would not be an issue, but since the timeout sets more timeouts, it is.
  2. In Carousel causes a memory leak.  #1414 it was stated that the cancel method needed to be called in the $destroy event. This is still true, but does not fix issue 1.

This PR uses setInterval instead of $timeout.

If we switched to using $interval in the 1.2.x branch, everything would still work the same. The syntax would be a little cleaner and the tests would not have a need for the jasmine.clock object.

Signed-off-by: Josh Kurz <josh.kurz@turner.com>
@@ -57,8 +57,6 @@ angular.module('ui.bootstrap.carousel', ['ui.bootstrap.transition'])
}
self.currentSlide = nextSlide;
currentIndex = nextIndex;
//every time you change slides, reset the timer
restartTimer();
Copy link
Contributor

Choose a reason for hiding this comment

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

@joshkurz Removing this one I think has a side effect on the time between transitions of the slides. What I mean is that if for example the interval is 5 sec and at 3 sec you move to the next slide, then that one will stay only for 2 sec instead of 5. There are no tests for this, but I think this is the expected behavior.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Makes sense. I'll get that back in there then. Good catch.

Thanks
Josh Kurz (mobile)

Signed-off-by: Josh Kurz <josh.kurz@turner.com>
@joshkurz
Copy link
Contributor Author

I didn't really like the idea of resetting the timer every time we call select. Sometimes the interval is actually on track and we dont need a new one. We only need a new interval if an un-pause event occurs, or the user clicks the next or prev button and interrupts the current interval.

So I added a clicked flag in the template and passed it down to the select function, so that goNext can tell if it needs to reset the interval.

There are a couple options for tests.

  1. Make restartTimer public on the controllers context and spy on it.
  2. Make the currentInterval variable public and check if its different when its supposed to be. (Maybe this could be good, because the interval could be canceled from anywhere in the app programmatically)

Wondering what way you guys think is best in terms of testing?

@chrisirhc
Copy link
Contributor

I'm wary of using setInterval as due to the reasons highlighted in this article. You also lose AngularJS's exception handling.

} else {
$scope.pause();
}
$timeout(angular.noop);
Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe this should be $scope.$apply().

Copy link
Contributor Author

Choose a reason for hiding this comment

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

causes digest errors. This is the safe way to run a digest without checking for the $$phase on the scope.

@bekos
Copy link
Contributor

bekos commented Dec 23, 2013

@joshkurz Sorry for the late response, but I am also not keen of replacing the $timeout with setInterval.
The reason is that this flow does not match to an event triggered in constant intervals, since this can either be interrupted by user's hover(pause) or change by selecting a new slide.

Also, I am not sure about the distinction you make between the transition made by clicking and the one made programmatically. I don't think there is a use case that someone will expect the timer not to be restarted, no mater how the transition was caused.

@pkozlowski-opensource
Copy link
Member

If I understand correctly this got fixed by #1451

@joshkurz
Copy link
Contributor Author

joshkurz commented Jan 4, 2014

so for the Angular 1.2 branch are we planning to use $interval?

On Mon, Dec 23, 2013 at 9:09 AM, Pawel Kozlowski
notifications@github.comwrote:

Closed #1423 #1423.


Reply to this email directly or view it on GitHubhttps://github.com//pull/1423
.

Josh Kurz
www.atlantacarlocksmith.com http://www.atlantacarlocksmith.com

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants