【问题标题】:clearTimeout and clearInterval not working on mobile devicesclearTimeout 和 clearInterval 在移动设备上不起作用
【发布时间】:2015-11-11 13:55:31
【问题描述】:

在移动设备(Android 和 iOS、手机和平板电脑)上清除标准 JavaScript 计时器时遇到问题。
我的页面包含 2 个按钮,一个播放/暂停切换和一个停止按钮(都是 FontAwesome 图标),其简单的 HTML 是:

<span class="fa fa-pause control-button" id="pause-button"></span>
<span class="fa fa-stop control-button" id="stop-button"></span>

间隔由以下函数启动:

var interval = function() {
    $('.control-button').fadeIn(300);
    //initiate the interval
    infiniteInterval = window.setInterval(Tiles.infiniteTick, speed); 
};

速度在较早的函数中定义(默认为 300)。 infiniteTick 是一个非常简单的函数,运行良好。我没有在这里解释它,因为它需要对整个程序的解释,但如果需要我可以提供代码。

播放和暂停切换如下:

$('body').on('click touchstart', '#pause-button', function() {
    if ($(this).hasClass('fa-pause')) {
        window.clearInterval(infiniteInterval);
        $(this).removeClass('fa-pause');
        $(this).addClass('fa-play');
    } else {
        infiniteInterval = window.setInterval(Tiles.infiniteTick, speed);
        $(this).removeClass('fa-play');
        $(this).addClass('fa-pause');
    }
});

最后,间隔以此结束(为简单起见,删除了一些纯粹的美学附加内容)

$('body').on('click touchstart', '#stop-button', function() {
    window.clearInterval(infiniteInterval);
    $('.control-button').fadeOut(300);
});

我最初通过研究认为这是由于点击事件未正确注册,但如您所见,我已将 touchstart 添加到所有点击事件中,这没有任何区别。它在所有桌面浏览器上都运行良好。

非常感谢任何帮助,我很乐意回答任何其他问题。

谢谢,

【问题讨论】:

  • 我相信同一个按钮有 2 个处理程序。我不确定它是否会起作用,但如果一个类是你想要决定的唯一方法,试试`$(element).hasClass()`。
  • 值得一提的是,在所有设备上,函数中的其他代码都可以正常执行。
  • 如果你可以使用 Mac,你可以尝试安装苹果的开发者工具,从那里你可以使用 iPhone/iPad 模拟器和 safari 来调试移动设备上的 javascript 问题。试试这个:webdesign.tutsplus.com/articles/…
  • 您在代码中的哪个位置声明infiniteInterval
  • 在包含这些函数的模块的开头,var infiniteInterval = null;

标签: javascript jquery mobile


【解决方案1】:

我已经设法解决了这个问题,事实证明这是双重的。

首先,点击事件触发了两次。使用此 SO 问题已解决此问题:jquery mobile click event fires twice

其次,我没有正确清除间隔。

由@MjrKusanagi 的 cmets 编辑

在每次调用setInterval() 之前简单调用clearInterval() 即可解决问题,确保在重新开始之前始终重置间隔。

原始粗略解决方法:

我打过电话

 infiniteInterval = null;

在每次clearInterval() 调用之后,以及将setInterval() 调用包装为

if (infiniteInterval === null)

感谢所有发表评论的人,希望这对某人有所帮助:)

【讨论】:

  • 将infiniteInterval 设置为null 不应清除间隔。事实上,我相当有信心这不是解决您问题的原因。变量infiniteInterval 只是保存一个整数。将其设置为另一个值(如 null)与实际清除间隔无关。
  • 我就是这么想的。不过,如果你知道我为什么想听的话,它可以工作:)
  • 检查它的 null 是否只是防止您在清除与其关联的间隔之前意外更改指针。我认为在将间隔设置为另一个值之前始终清除间隔会是一种更好的设计模式。
  • 如果您想自己测试一下: 1. 停止检查infiniteInterval 是否为空。 2. 然后在每个 setInterval 实例之前,添加对 clearInteral 的调用。
  • 如果您同意这是正确的解决方案,请编辑此答案并解释原因,然后接受您自己的答案。我也会对此表示赞同。
【解决方案2】:

首先,由于这句话,您的点击事件触发了两次:

$('body').on('click touchstart', '#pause-button', function() { ...

它监听clicktouchstart两个事件,因此它会被触发两次,一次在click事件上,一次在touchstart事件上。这也是您的代码在 PC 上运行良好的原因,因为 PC 浏览器中没有 touchstart 事件。

所以每次你触摸那个按钮时,都会发生这样的事情:

  • 第一个事件触发

    • 区间设置,句柄id为1(例如)

    • infiniteInterval = 1

  • 触发第二个事件

    • 另一个区间设置,句柄id为2

    • infiniteInterval = 2

现在运行的是两个计时周期,而不是一个,而您只能跟踪第二个。当您调用clearInterval 时,只有handle id = 2 间隔被清除,1 仍在运行。

所以解决办法是:

  1. 修复两次触发事件的问题,只听click。 (尝试fastclickzepto 或其他库来处理移动设备上的点击延迟)

  2. 正如您自己的回答所说,将infiniteInterval 设置为null,如果不是null,则永远不要开始另一个间隔。 (我认为它比“设置前总是清楚”更优雅,因为infiniteInterval 用作运行间隔的标志)

希望这些可以解决您的问题。

【讨论】:

    猜你喜欢
    • 2020-07-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-12
    • 2014-04-22
    • 1970-01-01
    • 2017-07-27
    • 1970-01-01
    相关资源
    最近更新 更多