每秒刷新日期的功能最终导致Chrome

时间:2017-04-07 20:21:27

标签: javascript google-chrome datetime time

我使用了一些函数来获取日期和时间,然后将它们推送到DOM中的元素。它似乎工作得很好,直到几分钟后脚本消耗内存的铬并崩溃页面。以下是我认为会影响我的问题的代码:

'use strict';

// ///////////////////////////// INITIAL /////////////////////////////////// //
function leading_0( num ) {
  if( num < 10 ) {
    num = '0' + num;
  }
  
  return num;
}

// ////////////////////////////// DATES //////////////////////////////////// //

function getCurrentTime( date ) {  // TIME / / / / / / / / / / / / / / / / / //
  var hours = date.getHours(),
      minutes = date.getMinutes(),
      seconds = date.getSeconds(),
      suffix = hours >= 12 ? 'PM' : 'AM',
      fullTime;

  hours = hours % 12;

  if( hours === 0 ){
    hours = 12;
  }

  minutes = leading_0( minutes );
  seconds = leading_0( seconds );
  fullTime = hours + ':' + minutes + ':' + seconds + ' ' + suffix;

  return fullTime;
}  // \\/ / / / / / / / / / / / / / / TIME / / / / / / / / / / / / / / / / / //

function getYear( date ) {  /// / / / YEAR / / / / / / / / / / / / / / / / / //
  var year = date.getFullYear();

  return year;
}  // \\/ / / / / / / / / / / / / / / YEAR / / / / / / / / / / / / / / / / / //

function getMonthDay( date ) {  /// MONTH DAY / / / / / / / / / / / / / / / ///
  var day = date.getDate();

  return day;
}  // \\/ / / / / / / / / / / / / / MONTH DAY / / / / / / / / / / / / / / / ///

function getMonth( date ) {  // / / / MONTH / / / / / / / / / / / / / / / / ///
  var months = [
    'January', 'Feburary', 'March',
    'April', 'May', 'June',
    'July', 'August', 'September',
    'October', 'November', 'December'
  ],
  month = months[ date.getMonth() ];

  return month;
}  // \\/ / / / / / / / / / / / / / / MONTH / / / / / / / / / / / / / / / / ///

function getWkDay( date ) {  /// / / WEEK DAY / / / / / / / / / / / / / / / ///
  var weekdays = [ 
    'Sunday', 'Monday', 
    'Tueday', 'Wednesday', 
    'Thursday', 'Friday', 
    'Saturday' 
  ],
  wkDay = weekdays[ date.getDay() ];

  return wkDay;
}  // \\ / / / / / / / / / / / / / / WEEK DAY / / / / / / / / / / / / / / / ///

function callBySec( func ) {
  setInterval( func, 1000 );
}

function pushDate(){  /// / / / / / PUSH DATES / / / / / / / / / / / / / / / //
  var today = new Date(),
      wkDay,
      month,
      day,
      year,
      time,
      d = document;
    
  wkDay = getWkDay( today );
  month = getMonth( today );
  day = getMonthDay( today );
  year = getYear( today );
  time = getCurrentTime( today );
  
  d.getElementById( 'wkDay' ).textContent = wkDay;
  d.getElementById( 'month' ).textContent = month;
  d.getElementById( 'day' ).textContent = day;
  d.getElementById( 'year' ).textContent = year;
  d.getElementById( 'time' ).textContent = time;
  
  callBySec( pushDate );
}  // \\/ / / / / / / / / / / / / / PUSH DATES / / / / / / / / / / / / / / / //

// ////////////////////////////// START //////////////////////////////////// //
function start() {
  pushDate();
}
start();
<p>
  <span id="wkDay"></span>, 
  <span id="month"></span> <span id="day"></span>, 
  <span id="year"></span> <b>|</b> <span id="time"></span>
</p>

上面的代码是一个主要的记忆猪吗?即使在这个SO页面上,它最终也会崩溃。有没有更好的方法来做到这一点并获得相同的结果?

4 个答案:

答案 0 :(得分:2)

取出这一行:

callBySec( pushDate );

pushDate()的末尾。您已经使用setInterval()每秒调用该功能,您不需要再次启动计时器。结果是您每秒都在创建另一个计时器。一分钟后,您每秒钟运行该功能60次。

如果callBySec使用setTimeout()而不是setInterval(),您的代码将是正确的。

然后start()函数应调用callBySec

&#13;
&#13;
'use strict';

function leading_0(num) {
  if (num < 10) {
    num = '0' + num;
  }

  return num;
}


function getCurrentTime(date) {
  var hours = date.getHours(),
    minutes = date.getMinutes(),
    seconds = date.getSeconds(),
    suffix = hours >= 12 ? 'PM' : 'AM',
    fullTime;

  hours = hours % 12;

  if (hours === 0) {
    hours = 12;
  }

  minutes = leading_0(minutes);
  seconds = leading_0(seconds);
  fullTime = hours + ':' + minutes + ':' + seconds + ' ' + suffix;

  return fullTime;
} 

function getYear(date) {
  var year = date.getFullYear();

  return year;
} 

function getMonthDay(date) { 
  var day = date.getDate();

  return day;
} 

function getMonth(date) { 
  var months = [
      'January', 'Feburary', 'March',
      'April', 'May', 'June',
      'July', 'August', 'September',
      'October', 'November', 'December'
    ],
    month = months[date.getMonth()];

  return month;
} 
function getWkDay(date) { 
  var weekdays = [
      'Sunday', 'Monday',
      'Tueday', 'Wednesday',
      'Thursday', 'Friday',
      'Saturday'
    ],
    wkDay = weekdays[date.getDay()];

  return wkDay;
}

function callBySec(func) {
  setInterval(func, 1000);
}

function pushDate() { 
  var today = new Date(),
    wkDay,
    month,
    day,
    year,
    time,
    d = document;

  wkDay = getWkDay(today);
  month = getMonth(today);
  day = getMonthDay(today);
  year = getYear(today);
  time = getCurrentTime(today);

  d.getElementById('wkDay').textContent = wkDay;
  d.getElementById('month').textContent = month;
  d.getElementById('day').textContent = day;
  d.getElementById('year').textContent = year;
  d.getElementById('time').textContent = time;
} 

function start() {
  callBySec(pushDate);
}
start();
&#13;
<p>
  <span id="wkDay"></span>,
  <span id="month"></span> <span id="day"></span>,
  <span id="year"></span> <b>|</b> <span id="time"></span>
</p>
&#13;
&#13;
&#13;

答案 1 :(得分:1)

尝试使用setTimeout()而不是setInterval(),因为后者会创建一个重复执行路径,而前者只是在未来的设定时间内运行一次代码块。

如果你拥有它,你每秒钟都会加倍pushDate()的定期执行次数。

答案 2 :(得分:0)

我完全期望这是OOM,因为你正在使用递归,并且永远不会爆发。

问题是你最终得到了一个

的调用链
pushDate -> callBySec -> pushDate -> callBySec -> PushDate -> etc

无穷。

你应该做的是完全摆脱callBySec,并改变你的开始方法以使用setInterval本身而不是依赖递归(你现在每秒都开始一个新的计时器)。 / p>

function start() {

    setInterval(pushDate, 1000);
}

答案 3 :(得分:0)

  

setInterval()方法以指定的时间间隔(以毫秒为单位)调用函数或计算表达式。   setInterval()方法将继续调用函数,直到调用clearInterval()或窗口关闭。

取自https://www.w3schools.com/jsref/met_win_setinterval.asp

所以,基本上,你调用你的函数pushDate,它启动一个定时器来每秒调用你的函数,每个被调用的函数都会启动另一个intervall。

如果你在start函数中调用intervall而不是递归 - 那就没关系了。