错误使用Javascript setInterval()

时间:2018-07-31 06:22:16

标签: javascript

我有一个使用JavaScript setInterval调用的函数,在某些情况下,该函数在未定义间隔间隙的情况下被多次调用(我怀疑这是因为未正确清除间隔,并且我正在创建多个间隔,但我不确定)。

我无法在本地重现该问题。

代码使用Twirl,但基本上是JS:

    function refreshCheckInRequests() {

        if (interval) { // If there is an interval running stop it.
            clearInterval(interval);
        }

        jsRoutes.controllers.ExtranetSecuredController.findPendingCheckInRequests("@gymId").ajax({ // Ajax call using Play Framework

            success: function (data) {

                $("#checkin-request-container").html(data);
                addRowListeners()
            },
            error: function (data) {

                if (data.status == 401) {

                    errorSwitchGym("@Messages("extranet.switch.gym")");
                    //location.reload();
                }
                else {
                    unexpectedError(data)
                }
            },
            complete: function() {

                interval = initInterval(); // At the end of the call init the interval again
            }
        });
    }

    function initInterval() {
        return setInterval(function () { refreshCheckInRequests(); }, 
    20000);
    }

    var interval;
    refreshCheckInRequests();

    $("#checkin-request-refresh").click(function (event) {

                refreshCheckInRequests();
                event.preventDefault();
            });

我可以改用setTimeout,因为最后我总是打一次refreshCheckInRequests,停止间隔,最后创建一个新间隔。

如果使用超时,则必须在超时回调执行结束时再次调用我的函数(就像我现在正在做的那样)。如果出现问题,我的回调将不再被调用。

无论如何,我想知道这里发生了什么。我想念什么吗?难道我做错了什么?有什么建议吗?

1 个答案:

答案 0 :(得分:1)

每次调用refreshCheckInRequests时都要清除当前间隔,但是在调用refreshCheckInRequests到分配新间隔之间会有一个延迟。由于refreshCheckInRequests也会在单击元素时运行,因此以下情况可能会导致间隔终止:

  1. 用户点击,清除当前间隔,运行异步findPendingCheckInRequests
  2. 用户再次单击,当前不存在间隔(无需清除),另一个异步findPendingCheckInRequests运行
  3. 来自第一个findPendingCheckInRequests的响应回来了。 complete处理程序运行,interval被分配给新间隔
  4. 来自第二个findPendingCheckInRequests的响应又回来了。 complete处理程序运行,interval被分配给新间隔 旧间隔

第一个创建的间隔仍在运行,但是不再存在对其的引用,因此第一个间隔将永远重复。

因此,尝试重新分配interval时清除间隔 ,确保每个新间隔都将始终清除旧间隔(如果正在运行旧间隔):

complete: function() {
  clearInterval(interval);
  interval = initInterval();
}