【问题标题】:Avoiding Infinite Loops避免无限循环
【发布时间】:2015-05-10 09:17:21
【问题描述】:

我是新手,请原谅我的无知。我试图通过本地存储获取一个计时器来告诉用户他们上次访问该页面的时间。但我却做了一个无限循环,我该如何纠正这个问题?在函数外调用函数?这会是什么样子?

$(document).ready(function(){
    var myDate = new Date(2015,4,9,0,0);
    localStorage["mydate"] = JSON.stringify(myDate);

    startTimer();
});

function startTimer() {
    setInterval(function(){
    var text = "It's been " + hoursSinceFirstVisit() + " hours since you first visited.";
    $('#timer').text(text);
 }, 1000);
}

function hoursSinceFirstVisit() {
    var currentDate = new Date();
    var lastDate = new Date(JSON.parse(localStorage["mydate"]));
    return hoursBetweenDates( lastDate, currentDate);
}
<div id="timer"></div>

谢谢!

【问题讨论】:

  • 您到底想达到什么目标?您的代码只会每秒钟更新一次自您第一次访问以来的小时数。这不是你想要的吗?你到底哪里有问题?
  • 好的,我在 Chrome 和 Firefox 中运行了你的脚本,它似乎工作正常。我从来没有遇到过“太多递归”的错误。您可以尝试的是省略 JSON 部分。只需使用myDate.toISOString() 将您的日期对象转换为字符串表示,然后使用new Date(localStorage["mydate"]) 取回日期对象。
  • 太好了,如果我想对 JSON 进行故障排除......我应该从哪里开始?
  • 什么意思?你是说它可以在没有 JSON 的情况下工作,而现在你想让它与 JSON 一起工作?

标签: javascript jquery infinite-loop


【解决方案1】:

没有提供hoursBetweenDates功能,所以我添加了一个。要调试递归错误,请尝试将匿名函数移动到重复调用的命名函数。将代码分解成更小的部分,并确保没有部分重复调用自身:

$(document).ready(function() {
  var myDate = new Date(2015, 4, 9, 0, 0);
  localStorage.mydate = JSON.stringify(myDate);

  function startTimer() {
    setInterval(updateMessage, 100);
  }

  function updateMessage() {
    var text = "It's been " + hoursSinceFirstVisit() + " hours since you first visited.";
    $('#timer').text(text);
  }

  // This is my function for getting hours between dates
  function hoursBetweenDates(d1, d2) {
    return Math.abs(d1 - d2) / 36e5;

    // For integer hours use this function
    // return Math.floor(Math.abs(d1 - d2) / 36e5);
  }

  function hoursSinceFirstVisit() {
    var currentDate = new Date();
    var lastDate = new Date(JSON.parse(localStorage.mydate));
    return hoursBetweenDates(lastDate, currentDate);
  }

  startTimer();
});

这可以正常工作而不会出现递归错误。这是demo。请注意,我让它返回自上次访问以来的小数精度小时,并将间隔设置为 100 毫秒以证明它工作正常。根据需要更新您的版本。抱歉,由于本地存储被禁用,我无法制作 Stack Snippet。

演示:http://jsbin.com/demevi/3/

【讨论】:

  • 谢谢!瞬间的赛车看起来棒极了!现在我必须编辑它*几个小时:)
  • 移动$(document).ready() 中的所有代码并声明updateMessage 函数更高级别应该是什么优势?我不明白这一点。
  • @BarrenessBogdanoff 使用Math.floor(Math.abs(d1 - d2) / 36e5);
  • @basilikum 用于调试递归错误。你似乎爱上了这个问题。没有别的事可做?
  • 好吧,您听起来好像写setTimeout(function () {}) 有问题,但事实并非如此。您没有提到原因是调试目的。这是有道理的。但在这种情况下,你的答案真的应该只是一个评论,因为你实际上并没有回答这个问题。我如何度过我的时间是我的事。
【解决方案2】:

函数setInterval() 安排一个函数重复执行,在每次运行前等待指定的毫秒数。

如果你想延迟函数hoursSinceFirstVisit()的执行(并且只运行一次)那么你必须使用setTimeout()

function startTimer() {
    setTimeout(function() {
       var text = "It's been " + hoursSinceFirstVisit() + " hours since you first visited.";
       $('#timer').text(text);
    }, 1000);
}

【讨论】:

  • 当我尝试这个时,我仍然在 Firefox 中得到过多的递归,并且在 Chrome 中超出了最大调用堆栈大小...... 抱歉,您将此函数放在我的脚本中的什么位置?
  • 总是这一行:
  • var lastDate = new Date(JSON.parse(localStorage["mydate"]));
  • Chrome 出现此错误:未捕获 RangeError:超出最大调用堆栈大小
猜你喜欢
  • 1970-01-01
  • 2019-05-01
  • 2022-01-15
  • 1970-01-01
  • 1970-01-01
  • 2023-02-05
  • 1970-01-01
  • 2021-09-21
  • 2021-03-07
相关资源
最近更新 更多