【问题标题】:Dynamically change Angular's $interval delay动态改变 Angular 的 $interval 延迟
【发布时间】:2018-01-24 21:37:04
【问题描述】:

我有一个旅游服务,它返回一个解析为旅游对象的承诺。游览对象有一些场景,每个场景都有一些热点。在主视图的控制器中,我有一个“私有”_init() 函数,它等待游览解决,然后设置一些东西。

我使用的间隔应该是一个一个无限地在场景中随机播放,但我希望场景之间的延迟基于当前活动场景的热点数量,例如有 2 个热点的场景应该持续 7.5 秒,有 1 个热点的场景应该持续 5 秒,以此类推。

这是我目前所拥有的:

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);
}

编辑:

我按照 quirimmo 的建议实现了一些新代码:

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);
}

直到现在我才收到f is not a function 异常。

【问题讨论】:

    标签: javascript angularjs settimeout


    【解决方案1】:

    你有一个$timeout,它在里面递归地调用另一个$timeout。等等。这意味着超时永远不会停止,因为它们会在内部执行的代码停止时停止。

    使用$interval 更改您的代码并在开始新代码之前清除之前的代码。它应该可以正常工作。

    附:同样,我认为您也可以在开始新的超时之前取消上一个超时。见$timeout.cancel方法

    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);
    }
    

    【讨论】:

    • 如果我理解正确,我应该修改我的_doTransition() 函数,让它在开始工作之前先取消间隔/超时?
    • 是的,您需要在开始新的超时之前清除超时。也许您可以在新的超时开始之前简单地添加这一行 _doTransition 并且它可能会起作用:$timeout.cancel(transition);。然后在那之后,开始你正在做的新超时
    • 对不起,我的错。不幸的是,我建议您进行的快速更改会产生相同的问题,因为在超时内您仍然会开始新的超时,因此它不会停止。更新答案贴出一点代码,在这里写代码太糟糕了:)
    • 哦,好吧,我没听懂。为什么您不使用$interval 作为我的第一个建议重新考虑您的逻辑?它将始终在后台运行,然后使用条件进行检查以清除间隔并以您想要的新持续时间开始新的间隔。有意义吗?
    • 对不起,代码不应该有()。请试试这个:transition = $timeout(_doTransition, duration);
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多