Reputation: 12
I have a tour service that returns a promise which resolves to a tour object. The tour object has some scenes, and each scene has some hotspots. In the main view's controller, I have a "private" _init()
function that waits for the tour to resolve and then sets up some stuff.
I am using an interval that is supposed to shuffle through the scenes one by one ad infinitum, but I want a delay between the scenes to be based on the number of hotspots of the currently active scene, e.g. a scene with 2 hotspots should last for 7.5 seconds, a scene with 1 hotspot should last for 5 seconds, etc.
Here's what I have so far:
var i = 0, ready, scenesCount, activeScene, duration, transition = null;
_init();
// Later on down...
function _init()
{
ready = false;
AlexaTourApi.getTour( null).then( function ( res) {
$log.log( 'AlexaTourController got tour', res);
$scope.tour = res;
scenesCount = $scope.tour.scenes.length;
activeScene = 0;
duration = (getActiveScene().hotspots.length + 1) * 2500;
ready = true;
transition = $timeout( _doTransition(), duration);
});
}
function _doTransition()
{
activeScene = (i++ % scenesCount);
duration = (getActiveScene().hotspots.length + 1) * 2500;
transition = $timeout( _doTransition(), duration);
}
EDIT:
I implemented some new code as per quirimmo's suggestion:
function _init()
{
ready = false;
AlexaTourApi.getTour( null).then( function ( res) {
$log.log( 'AlexaTourController got scenes', res);
$scope.tour = res;
scenesCount = $scope.tour.scenes.length;
activeScene = 0;
duration = (getActiveScene().hotspots.length + 1) * 2500;
ready = true;
_resetInterval();
});
}
function _resetInterval()
{
if ( transition !== null) {
$interval.cancel( transition);
}
duration = (getActiveScene().hotspots.length + 1) * 2500;
transition = $interval( _doTransition(), duration);
}
function _doTransition()
{
activeScene = (i++ % scenesCount);
}
Only now I'm getting an f is not a function
exception.
Upvotes: 1
Views: 515
Reputation: 9988
You have a $timeout
which calls recursively another $timeout
inside. And so on. This means that the timeouts will never stop, because they stop when the code executed inside will stop.
Change your code using $interval
and before to start the new one, clear the previous one. And it should work fine.
P.s. equivalently I think you can also cancel the prev timeout before to start the new one. See $timeout.cancel
method
var i = 0,
ready, scenesCount, activeScene, duration, transition = null;
_init();
// Later on down...
function _init() {
ready = false;
AlexaTourApi.getTour(null).then(function(res) {
$log.log('AlexaTourController got tour', res);
$scope.tour = res;
scenesCount = $scope.tour.scenes.length;
activeScene = 0;
duration = (getActiveScene().hotspots.length + 1) * 2500;
ready = true;
clearTimeoutAndStartNewOne();
});
}
// here we clear the timeout and then we start a new one which is connected to the other function
function clearTimeoutAndStartNewOne() {
if (transition !== null) {
$timeout.cancel(transition);
}
duration = (getActiveScene().hotspots.length + 1) * 2500;
transition = $timeout(_doTransition, duration);
}
// here we simply implement the logic of the timeout to be repeated
function _doTransition() {
activeScene = (i++ % scenesCount);
}
Upvotes: 2