我可以在另一个setTimeout中有一个setTimeout吗?

时间:2012-12-14 22:32:06

标签: javascript settimeout

这是一个快速(破产)的jsfiddle:http://jsfiddle.net/wH2qF/

由于某种原因这不起作用......是因为我在另一个setTimeout中有一个setTimeout吗?

$(function() {
   $("#Volume").click(function() {
      setTimeout(triggerVolumeChange, 4000);
      function triggerVolumeChange() 
      {
          var volumeDiv = document.getElementById("volumeNumber");
          var volumeOld = 8;
          var volumeNew = 37;
          var timeNew = (1000/(volumeNew-volumeOld));
          changeVolume();

          function changeVolume()
          {
             volumeDiv.innerHTML = volumeOld;
             volumeOld++;
             if (volumeOld <= volumeNew) setTimeout(changeVolume, timeNew);
          };
      });
});

为了清楚起见,我应该指明我从Click函数中删除了其他东西,并且澄清了什么不能正常工作,好吧,基本上,我点击并没有任何反应,而如果我删除了这一块代码它的工作原理很好...实际上变量的设置也可以正常工作(我自然是假设的)但是当我粘贴或取消注释changeVolume()函数时,点击会再次停止工作...有什么想法吗?

-

另一个澄清:我想要做的是,点击时,在一个字符串中模拟从值8到37的音量..因此该函数内的setTimeout。

-

根据你的家伙的要求,这是整个代码......我怀疑它是否有意义,但这里是......仅供参考,点击这将触发大量动画以模拟应用程序的流程我'设计..

<script>
            $(function() {
                $("#Volume").click(function() {

                    var userPrompt = document.getElementById("userPrompt")
                    userPrompt.innerHTML = "Change volume to 37";

                    var avatarIcon = document.getElementById("avatarIcon");
                    avatarIcon.innerHTML = "<img src='imgs/haloIcons-volume_82x76.png' alt='Volume'/>";

                    var hints = document.getElementById("hints");
                    hints.style.opacity = 0;
                    $(".dragonTvOut").toggleClass("dragonTvIn");

                    setTimeout(triggerP, 1000);
                    function triggerP()
                    {
                        var halo = document.getElementById('avatar');
                        if( 'process' in halo ) { 
                            halo.process();
                        };
                    };

                    setTimeout(triggerUserPrompt, 2000);
                    function triggerUserPrompt() 
                    {
                        document.getElementById("userPrompt").className = "userPromptIn";
                    };

                    setTimeout(triggerVolumeChange, 4000);
                    function triggerVolumeChange() 
                    {
                        document.getElementById("userPrompt").className = "userPromptEnd";

                        var halo = document.getElementById('avatar');
                        if( 'resume' in halo ) { 
                            halo.resume();
                        }

                        document.getElementById("avatarIcon").className = "avatarIconEnd";

                        var volumeDiv = document.getElementById("volumeNumber");
                        var volumeOld = 8;
                        var volumeNew = 37;
                        var timeNew = (1000/(volumeNew-volumeOld));
                        changeVolume();

                        function changeVolume()
                        {
                            volumeDiv.innerHTML = volumeOld;
                            volumeOld++;
                            if (volumeOld <= volumeNew) setTimeout(changeVolume, timeNew);
                        }​;

                        var side = 100;
                        var paper = new Raphael(volumeArcAnim, 100, 300);

                        paper.customAttributes.arc = function (xloc, yloc, value, total, R) {

                            var alpha = 360 / total * value,
                                a = (90 - alpha) * Math.PI / 180,
                                x = xloc + R * Math.cos(a),
                                y = yloc - R * Math.sin(a),
                                path;
                            if (total == value) {
                                path = [
                                    ["M", xloc, yloc - R],
                                    ["A", R, R, 0, 1, 1, xloc - 0.01, yloc - R]
                                ];
                            } else {
                                path = [
                                    ["M", xloc, yloc - R],
                                    ["A", R, R, 0, +(alpha > 180), 1, x, y]
                                ];
                            }
                            return {
                                path: path
                            };
                        };

                        var arcWidth = 87;
                        var strokeRadius = arcWidth/2;

                        var indicatorArc = paper.path().attr({
                            "stroke": "#ffffff",
                            "stroke-width": 3,
                            arc: [side/2, side/2, 12, 100, strokeRadius]
                        });

                        indicatorArc.animate({
                            arc: [side/2, side/2, 60, 100, strokeRadius]
                        }, 1500, "<>", function(){
                            // anim complete here
                        });

                    };

                });
            });
            </script>

5 个答案:

答案 0 :(得分:3)

在您的破碎示例中http://jsfiddle.net/wH2qF/存在一些问题

  • 你忘了告诉jsfiddle使用jQuery
  • 卷范围的ID(在JS中)为ph,但应为volumeNumber(如HTML中所示)

Click here to see a working version

如果您从jsfiddle中的库中选择了jQuery,您会看到错误

  

未捕获的TypeError:无法设置null

的属性'innerHTML'

这让我相信你的jsfiddle不能很好地代表你的问题。也许尝试创建另一个减少,因为你添加的只有“愚蠢”的错误?

答案 1 :(得分:2)

您错过了}

$(function() {
   $("#Volume").click(function() {
      setTimeout(triggerVolumeChange, 4000);
      function triggerVolumeChange()
      {
          var volumeDiv = document.getElementById("volumeNumber");
          var volumeOld = 8;
          var volumeNew = 37;
          var timeNew = (1000/(volumeNew-volumeOld));
          changeVolume();

          function changeVolume()
          {
             volumeDiv.innerHTML = volumeOld;
             volumeOld++;
                 if (volumeOld <= volumeNew) setTimeout(changeVolume, timeNew);
          };
      } // that one was missing
   });
});

答案 2 :(得分:1)

是的,您可以在另一个内部使用setTimeout() - 这是用于重复定时事件的典型机制。

你的工作不起作用的原因与setTimeout()本身无关;这与你嵌套函数的方式有关。

changeVolume()内的triggerVolumeChange()函数意味着您无法使用其名称直接引用它。

最快的解决方案是删除嵌套,以便changeVolume()位于根级别而不是嵌套在triggerVolumeChange()内。

答案 3 :(得分:0)

如果您不想使用setInterval(),可以使代码适用于这些更改:

$(function() {
    $("#Volume").click(function() {
        setTimeout(triggerVolumeChange, 4000);
        function triggerVolumeChange () {
            var volumeDiv = document.getElementById("volumeNumber");
            var volumeOld = 8;
            var volumeNew = 37;
            var timeNew = (1000/(volumeNew-volumeOld));
            var changeVolume = function () {
                volumeDiv.innerHTML = volumeOld;
                volumeOld++;
                if (volumeOld <= volumeNew) setTimeout(changeVolume, timeNew);
            };
            changeVolume();
        }
    });
});

jsFiddle的工作演示。

答案 4 :(得分:0)

从技术上讲,计时器从何处开始没有区别。在大多数情况下,它是作为带有标识符和关联的回调处理程序的计时器列表实现的。

因此,如果您的逻辑正确,那就可以了。没有带来无限调用序列的不可预测条件,也没有无限数量的超时实例,等等。

例如模仿setInterval函数:

// Bad (unexpected multiple sequences started per each event)

const handler = () => {
  setTimeout(handler)
}

<Button onClick={handler} />
// Good (previous interval closed before start new one)

const [id, idUpdate] = useState(-1)

const handler = () => {
  const id = setTimeout(handler)
  idUpdate(id)
}

const start = () => {
  if(id !===-1) clearTimeout(id)
  idUpdate(-1)
  handler()
}

<Button onClick={start} />

或其他

// Bad (infinite events with small time will take all cpu time)

const handler = () => {
  setTimeout(handler, 0) // actually mean several ms
}
// Good (special condition for finish iterations)

let count = 20

const handler = () => {
  if(!count) return
  count--
  setTimeout(handler, 0)
}