Ошибка в работе таймера с паузой

341
31 октября 2017, 01:09

Приветствую. Столкнулся с проблемой в реализации таймера с паузой. Пауза не удаляет интервал, хотя должна.

http://jsfiddle.net/acqhr6y8/

function Timer(callback, delay) { 
  var start = new Date().getTime(); 
  var countDownDate = start + delay; 
  var timerId, start, remaining = delay; 
   
  this.pause = function() { 
    window.clearTimeout(timerId); 
    remaining -= new Date() - start; 
    clearInterval(this.cutdown); 
  }; 
 
  this.resume = function() { 
    start = new Date(); 
    window.clearTimeout(timerId); 
    timerId = window.setTimeout(callback, remaining); 
    setInterval(this.cutdown, 1000); 
  }; 
 
  this.cutdown = function() { 
    remaining = remaining - 1000; 
    minutes = Math.floor((remaining % (1000 * 60 * 60)) / (1000 * 60)); 
    seconds = Math.floor((remaining % (1000 * 60)) / 1000); 
    (remaining < 0) ? clearInterval(this.cutdown) : $("#time").html(minutes + "m " + seconds + "s"); 
  }; 
 
  this.resume(); 
} 
var timer = new Timer(function() { 
  $("#status").html("Stoped"); 
}, 30000); 
$("#pause").click(function() { 
	timer.pause(); 
});	 
$("#resume").click(function() { 
	timer.resume(); 
});	
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script> 
<div id="time"> 
</div> 
<div id="status"> 
  Up 
</div> 
<div id="pause"> 
  pause 
</div> 
<div id="resume"> 
  resume 
</div>

Скорее всего напутал с интервалом, но не смог понять где.

Answer 1

clearInterval, так же как и clearTimeout, принимает id таймера.

В коде в вопросе ему передается функция.

В свою очередь, нигде не сохраняется результат setInterval(this.cutdown, 1000); который и следовало бы передать в clearInterval

Для решения, нужно добавить дополнительную переменную, для хранения интервала и использовать ее аналогично имеющемуся timerId.

Кроме того, похоже логическая ошибка в методе pause. В нем не нужно менять remaining пытаясь связать с локальным временем, так как это состояние таймера и оно не должно меняться, пока таймер остановлен.

function Timer(callback, delay) { 
  var timerId, intervalId, start, remaining = delay; 
 
  this.pause = function() { 
    window.clearTimeout(timerId); 
    clearInterval(intervalId); 
  }; 
 
  this.resume = function() { 
    window.clearTimeout(timerId); 
    clearInterval(intervalId); 
    timerId = window.setTimeout(callback, remaining); 
    intervalId = setInterval(this.cutdown, 1000); 
  }; 
 
  this.cutdown = function() { 
    remaining = remaining - 1000; 
    minutes = Math.floor((remaining % (1000 * 60 * 60)) / (1000 * 60)); 
    seconds = Math.floor((remaining % (1000 * 60)) / 1000); 
    (remaining < 0) ? clearInterval(intervalId): $("#time").html(minutes + "m " + seconds + "s"); 
  }; 
 
  this.resume(); 
} 
var timer = new Timer(function() { 
  $("#status").html("Stoped"); 
}, 30000); 
$("#pause").click(function() { 
  timer.pause(); 
}); 
$("#resume").click(function() { 
  timer.resume(); 
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script> 
<div id="time"> 
</div> 
<div id="status"> 
  Up 
</div> 
<div id="pause"> 
  pause 
</div> 
<div id="resume"> 
  resume 
</div>

Answer 2

Попробуйте такой синтаксис

var timerId = setTimeout(...);
clearTimeout(timerId);

дело в том что вам нужно разобраться с передачей параметров, временем и областью видимости переменных(как было указано выше)... я не знаю какая там у вас задача, но можно поступить проще, например таймер не останавливать, а менять переменную приращения - delta:

<!doctype html> 
<html> 
<head> 
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script> 
 
<script> 
 
function Timer(callback, delay) { 
  var start = new Date().getTime(); 
  var timerId, remaining = delay, delta =1000; 
   
  this.pause = function() { 
	$("#status").html("Paused"); 
	delta = 0; 
  }; 
  this.resume = function() { 
	$("#status").html("Up"); 
	delta = 1000;     
  }; 
 
  this.cutdown = function() { 
    remaining = remaining - delta; 
    minutes = Math.floor((remaining % (1000 * 60 * 60)) / (1000 * 60)); 
    seconds = Math.floor((remaining % (1000 * 60)) / 1000); 
    $("#time").html(minutes + "m " + seconds + "s");	 
    if (remaining <= 0)  {clearInterval(timerId);callback();}  
  }; 
timerId = setInterval(this.cutdown, 1000);   
} 
</script> 
</head> 
<body> 
 
<div id="time"> 
</div> 
<div id="status"> 
  Up 
</div> 
<div id="pause"> 
  pause 
</div> 
<div id="resume"> 
  resume 
</div> 
	 
<script> 
var timer = new Timer(function() { 
$("#status").html("Stoped"); 
}, 30000); 
 
$("#pause").click(function() {   
	timer.pause(); 
});	 
$("#resume").click(function() { 
	timer.resume(); 
}); 
</script> 
 
</body> 
</html>

или нужно всё таки с запуском и остановкой таймеров работать? тогда в идеале нужно будет учесть еще время работы самого скрипта, загрузку браузера и их особенности

READ ALSO
Как сделать поиск и замену в тексте?

Как сделать поиск и замену в тексте?

Есть HTML текст, в котором встречаются несколько []

379
Асинхронный каунтер на python

Асинхронный каунтер на python

ЗдравствуйтеЕсть вот такой простой код на javascript:

321
React, Gulp. Не загружаются стили

React, Gulp. Не загружаются стили

Пишу приложение с использованием React, Node, GulpВозникла проблема с подключением стилей в компонент

331
Node.js socket.io не может подключиться к серверу

Node.js socket.io не может подключиться к серверу

Здравствуйте, делаю nodejs сервер для уведомлений и сообщений

403