【问题标题】:Javascript for loop that adds dates to array freezes the page on certain PCs将日期添加到数组的 Javascript for 循环会冻结某些 PC 上的页面
【发布时间】:2020-02-24 22:07:48
【问题描述】:

在运行我创建的一个 ASP 页面时,我遇到了一个奇怪的问题。我已经在几台电脑上测试了网页,只有少数电脑能够正确显示页面。对于我测试过的大多数 PC,页面完全加载并且功能齐全。对于某些人来说,页面冻结并且 Chrome 显示它正在等待缓存或等待服务器 - 所有输入字段都是 不可点击。另一方面,该页面在 Edge 上非常适合他们。有一台 PC 上的页面在 Chrome 和 Edge 上都不起作用。每台电脑都有相同版本的 Windows 10、相同版本的 Chrome 和 Edge。

在注释掉一些代码后,我发现有一个特定的 for 循环会导致某些 PC 上的崩溃。基本上,我要做的是显示某些日期范围的数据,如果该日期范围内的日期没有数据,通常会丢失,因此,我将其添加到下面的 for 循环中稍后将 0 值分配给该日期,以便我有一个布局良好且日期连续的表格。

// Checking if there are no missing dates in the date range. This could happen if the date doesn't exist in the SQL database.
for (var i = 0; i < dateArray.length - 1; i++) {
    // Checking if the next date is only incremented by 1
    var currentDate = GetDate(dateArray[i]);
    var nextDate = GetDate(dateArray[i + 1]);
    var shouldBeNextDate = GetNextDayDate(currentDate);

    // Adding the date that is missing. If the date won't be found later the quantities will be set to 0.
    if (convertDateToString(shouldBeNextDate) != convertDateToString(nextDate)) {
        dateArray.splice(i + 1, 0, convertDateToString(shouldBeNextDate));
    }
}

// Returns Date() from string
function GetDate(date){
    var numbers = date.match(/\d+/g);
    return new Date(numbers[2], numbers[1] - 1, numbers[0]);
}

// Returns the next day of the Date() passed as an argument
function GetNextDayDate(date){
    var numbers = convertDateToString(date).match(/\d+/g);
    return new Date(numbers[2], numbers[1] - 1, parseInt(numbers[0]) + 1);
}

// Returns Date() converted to string 
function convertDateToString(strDate){
    // Setting to MM/dd/YYYY format
    strDate = new Date(strDate).toLocaleDateString();
    var firstDash = strDate.indexOf("/");
    var secondDash = strDate.indexOf("/", firstDash + 1);
    var tempMM = strDate.substr(0, firstDash);
    var tempDD = strDate.substr(firstDash + 1, secondDash - firstDash - 1);
    var tempYYYY = strDate.substr(strDate.length - 4, 4);

    return tempDD + "/" + tempMM + "/" + tempYYYY;
}

当上面的for循环被注释掉时,页面加载成功。任何想法可能导致问题?有什么我缺少的直截了当的东西吗?

【问题讨论】:

  • 请注意,在您的编辑中,您添加了一对大括号,这可能会修改代码的行为方式。我认为您错误地从另一个 rejected edit 中提取了这些内容,因此您可能需要检查一下。
  • @CalvT - 我确实在编辑中添加了大括号,但在这个特定示例中,大括号不会改变原始代码中的行为。不过,当它们与不正确的缩进结合在一起时,它们确实给我带来了困惑,因为我认为大括号匹配错误。
  • @Andrew 好的,我知道的不够多,无法自己做出判断。但是,对于未来,一般做法是将代码编辑留给 OP,因为无意的编辑可能会改变它的工作方式。建议 OP 如何改进的评论可能是最好的事情。我知道你的意图是好的,所以谢谢你的贡献:)
  • convertDateToString 函数在格式化日期时使用了糟糕的策略。 toLocaleDateString 的结果取决于实现,并且可能取决于系统设置。最好使用 getFullYear、getMonth 等并自己格式化字符串。见How to format a JavaScript date。

标签: javascript arrays string google-chrome date


【解决方案1】:

问题在于这段代码:

strDate = new Date(strDate).toLocaleDateString();

尽管您在 cmets 中声明这将给出 MM/dd/YYYY 格式的字符串表示,但这并不能保证。 正如mdn(斜体字)上所记录的那样:

toLocaleDateString() 方法返回一个字符串,该字符串具有该日期的日期部分的语言敏感 表示。

例如,当我在浏览器的控制台中键入以下内容时:

new Date().toLocaleDateString()

...然后在 FireFox 中我得到:

“2019 年 10 月 29 日”

这是你所期望的,但在 Chrome 中我得到了:

“29-10-2019”

显然,对于 my 语言环境的真正含义存在一些混淆。然而重要的是,假设任何格式都是错误的(除非您将参数传递给toLocaleDateString,使其独立于您当前的语言环境)。

假设您将 Date 对象 10/29/2019 传递给 convertDateToString:在后一种情况下它会 在.toLocaleDateString 返回的字符串中甚至找不到任何斜杠,因此它返回的字符串本身将是 “//2019”。当GetNextDayDate 试图从中创建一个 Date 对象时,它会返回一个无效的 Date。

因此,循环中的if 条件将始终为真,并且新条目将被拼接到您的数组中, 使数组的长度更大,因此循环永远不会结束。

解决方案是仅在真正需要时执行日期到字符串的转换, 当你这样做时,使用 Date 方法来提取日期部分,而不是 toLocaleDateString。

以下是更正后的代码:

for (var i = 0; i < dateArray.length - 1; i++) {
    var currentDate = GetDate(dateArray[i]);
    var nextDate = GetDate(dateArray[i + 1]);
    var shouldBeNextDate = GetNextDayDate(currentDate);

    // No need to convert to String
    if (shouldBeNextDate < nextDate) {
        dateArray.splice(i + 1, 0, convertDateToString(shouldBeNextDate));
    }
}
console.log(dateArray);

function GetDate(date){
    var numbers = date.match(/\d+/g);
    return new Date(numbers[2], numbers[1] - 1, numbers[0]);
}

function GetNextDayDate(date) { // Don't convert to string here.
    date = new Date(date); // clone the date
    date.setDate(date.getDate() + 1); // add one day to it
    return date;
}

function convertDateToString(date) {
    // Get the date parts directly
    let tempMM = date.getMonth() + 1;
    let tempDD = date.getDate();
    let tempYYYY = date.getFullYear();

    // Pad with zeroes where needed
    return (tempDD + "/" + tempMM + "/" + tempYYYY).replace(/\b\d\b/g, "0$&");
}

【讨论】:

  • 对我来说,在 toLocaleString 中使用“locale”是一种误称,会造成混淆。它基于语言代码,实际上与用户所在的位置或他们喜欢或通常使用的日期格式无关。因此,我认为 toLocaleString 用于日期的任何使用都是令人担忧的,因为它假定语言代码足以确定用户通常使用的日期格式,并且结果不一定一致。 (我认为这是解释我的支持的一种冗长的方式)。
猜你喜欢
  • 1970-01-01
  • 2012-09-06
  • 1970-01-01
  • 2020-05-30
  • 1970-01-01
  • 2020-10-22
  • 2012-10-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多