Страницы

Поиск по вопросам

Показаны сообщения с ярлыком setinterval. Показать все сообщения
Показаны сообщения с ярлыком setinterval. Показать все сообщения

пятница, 14 февраля 2020 г.

setTimeout внутри setInterval, не получается установить интервал setTimeout

#setinterval #settimeout


Сделала анимацию: привидение появляется и исчезает. Причем время его присутствия
меньше, чем отсутствия, чего я и добивалась.

Но время присутствия не поддается регулированию, а, такое впечатление, что зависит
от времени всего интервала t

var t = setInterval(function appear(){
    var ghost = document.getElementById("ghost");
    if (ghost.style.display == "none")
            {ghost.style.display = "block";}
    else
            {var t1 = setTimeout(function disappear(){
            ghost.style.display = "none";
            }, 1)}      
}, 6000)


Исчезнуть оно должно по функции t1. Хочется сделать еще меньше. Задержка t1 урезана
до 1 мс, но никакой реакции. Отчего это?



var t = setInterval(function appear() {
  var ghost = document.getElementById("ghost");
  if (ghost.style.display == "none") {
    ghost.style.display = "block";
  } else {
    var t1 = setTimeout(function disappear() {
      ghost.style.display = "none";
    }, 1)
  }
}, 6000)
body {
  background: black url(https://s.cdpn.io/16327/texture_bg.jpg) no-repeat 50% 0px;
}

#ghost {
  position: absolute;
  left: 25%;
  display: none;
}




    


Ответы

Ответ 1



Проблема Вашего кода в том, что ожидание disappear вы пишете в ветке else. Это значит, что у этой ветки нет шансов выполниться на текущей итерации setInterval. Чтобы контроллировать время исчезновения, нужно выставлять setTimeout непосредственно после отображения. Вторая проблема в проверке: ghost.style.display == "none" Это не работает для стилей, полученных через каскадные таблицы (т.е. если стиль указан не для самого элемента, а каким-то образом в css). Можно либо вручную инициализировать стиль элемента, либо использовать getComputedStyle чтобы получить актуальные стили элемента после применения css. var ghost = document.getElementById("ghost"); ghost.style.display = "none"; var t = setInterval(function appear() { if (ghost.style.display == "none") { ghost.style.display = "block"; // Просто убираем else setTimeout(function () { ghost.style.display = "none"; }, 300) } }, 3000) body { background: black url(https://s.cdpn.io/16327/texture_bg.jpg) no-repeat 50% 0px; } #ghost { position: absolute; left: 25%; display: none; }

Ответ 2



Так Вы можете менять промежутки времени видимой/невидимой картинки, изменяя значения переменных showSeconds и hideSeconds. var hideSeconds = 3; var showSeconds = 1; function switchGhost(show) { var ghost = document.getElementById("ghost"); if (show) { ghost.style.display = "block"; setTimeout(switchGhost, showSeconds * 1000, !show); } else { ghost.style.display = "none"; setTimeout(switchGhost, hideSeconds * 1000, !show); } } switchGhost(false); body { background: black url(https://s.cdpn.io/16327/texture_bg.jpg) no-repeat 50% 0px; } #ghost { position: absolute; left: 25%; display: none; }

среда, 12 февраля 2020 г.

setInterval и задержки

#javascript #setinterval


День добрый, Господа! При написании скрипта столкнулся с такой проблемой: я задал
переменной значение, затем я подставил эту переменную в setInterval в задержку, однако
при изменении этой переменной интервал между выполнениями функции не изменялся. Возник
вопрос: можно ли вообще подставить переменную как значение задержки в setInterval.
Такой код есть на данный момент, передаю вам штурвал.



setInterval(ggg, 1000);
var iter = 0;
var pulse = 90;
var time = 100;
setInterval(timer, 1000);
function ggg() {
	var aza = setInterval(ggg, 1000);
	setTimeout(ggg, 1000);
	clearInterval(aza);
	var aza = setInterval(ggg, 2000);
};
function pulsing() {
	heart.style.backgroundColor = 'red';
	setTimeout(back, 300);
		function back() {
			heart.style.backgroundColor = 'black';
		};
};
function timer() {
	time--;
};



	
	Kek
	



Ответы

Ответ 1



Нет, переменную как значение задержки в setInterval подставить нельзя, вот почему: setInterval выполняет код много раз через равные промежутки времени, пока он не будет остановлен вызовом clearInterval. т.е. промежуток задается один раз (при вызове setInterval). Для того, чтобы сделать так, как вы хотите - нужно каждый раз "уничтожать" setInterval и заново создавать его, с уже новым промежутком(который есть у вас в переменной). PS. это можно сделать разными способами, как один из возможных - при помощи Object.prototype.watch() (учитывая его не поддержку:D, можно юзать - полифилл). var timerObj = { interval: 0, timerId: 0, func: my_function}; // объект для интервала timerObj.watch('interval', function(prop, oldval, val) { // тут пересоздавать сам setInterval нужно: if(timerObj.timerId) clearTimeout(timerObj.timerId); timerObj.timerId = setInterval(this.func, val); }); timerObj.interval = 1000; // запустили интервал // много кода timerObj.interval = 5000; // в любом месте меняет, он сам пересоздается) // можно еще придумать методы для полной остановки и т.д. PPS. как в комментариях верно подметили - лучше использовать Object.defineProperty, тогда код выглядел бы так(полифилл не нужен): var timerObj = {timerId: 0, func: my_function}; // объект для интервала Object.defineProperty(timerObj, 'interval', { set:function(val){ if(timerObj.timerId) clearTimeout(timerObj.timerId); timerObj.timerId = setInterval(timerObj.func, val); } }); timerObj.interval = 1000; // много кода timerObj.interval = 5000;

Ответ 2



Под переменной ты понимаешь: переменный период интервала. Период в setInterval статичен - прямо в вызове setInterval нельзя его сделать переменным. Но можно сделать переменный интервал времени другими способами. Держи пример - каждый шаг таймера произвольный, от 0 до 1 сек: var someAction = function(){ console.log(new Date()); //clearTimeout на случай - чтобы при множественном запуске someAction вне, всё было ОК clearTimeout(someAction.timeout); someAction.timeout = setTimeout(someAction, Math.random()*1000); }; someAction();

Ответ 3



В вашем мире слишком много магии. Для начала, вам следует осознать: любое выражение, которое вы напишите, будет вычислено сразу же, еще до того как кто-то воспользуется его значением. Передача переменной в setInterval ничем не отличается от передачи константы. Для того, чтобы изменить интервал выполнения - надо пересоздать таймер. Вставлять вызов пересоздание таймера каждый раз когда надо изменить интервал - неправильно и нарушает принцип DRY ("не повторяйся!"). Поэтому лучше инкапсулировать таймер в объект: function Timer (callback, interval) { this.callback = callback; this.timerId = null; this.setInterval(interval); } Timer.prototype.setInterval = function (interval) { if(this.timerId !== null) clearInterval(timerObj.timerId); this.timerId = setInterval(this.callback, val); } // ... var timer = new Timer(some_function, 1000); // ... timer.setInterval(5000);

среда, 1 января 2020 г.

Повторение кода через разные промежутки времени Javascript

#javascript #setinterval #settimeout


Здравствуйте. 
Мне нужно реализовать следующую логику:  
  1 этап: пользователи что-то делают на сервере - 40 секунд  
  2 этап: выполняется процесс - случайное кол-во секунд (от 3 до 10)  
  3 этап: кулдаун - пользователи любуются результатом - 2 секунды  
и все повторяется с начала и так вечно

setInterval не подходит, так как в нем код повторяется через РАВНЫЕ промежутки времени,
а время окончания работы моего кода становится известно только в процессе. Если же
использовать время интервала с запасом, то 3 этап будет выполняться то 2 секунды, то
15 - неприемлемо.

Такое решение (рекурсия)



function round() {
    var delay = 20000 * Math.random(); //узнаем, через сколько в этот раз должен
сработать код
    setTimeout(function () {

        console.log('Hellow world!');//что-то тут делаю
        round(); //и перезапускаю

    }, delay);
}

round();




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

явно ведь должно быть красивое и правильное решение? что в таком случае использовать?
Нужно сделать так, чтобы была какая-то асинхронная функция с примерно таким содержанием:

-сообщить о начале 1 этапа (использую socket.io)  
-ждать 40 секунд  
-сообщить о начале 2 этапа  
-ждать случайное кол-во секунд  
-сообщить о начале третьего  
-ждать 2 секунды

потом функция должна запуститься заново но не рекурсией. И хотелось бы без вложенных
друг в друга setTimeout. И не подобным "Войне и Миру" кодом.
    


Ответы

Ответ 1



Вложеные setTimeout стек не забивают, так как выполняются асинхронно, их бояться не надо. Для решения вашей ситуации вам надо написать самому какую-то timing микро библиотеку, позволяющую создавать цепи событий с таймаутами. Это что-то типа промисов в fetch. Выглядеть этот код будет примерно так TimeoutChain.PlusOne(() => { /*...*/ },2000) .PlusOne(() => { /* ещё код*/ },3000).StartChain(); Реализация будет на основе setTimeout. Но это будет выглядеть красиво, так как она инкапсулирована в эту функцию, так же из-за её асинхронности стек она не будет забивать. Так как каждая функция вызывает свой setTimeout а сама завершается. Тут в примере пауза явно задаётся в цепи, но можно её значение просто например возвращать из самой лямбды.

Ответ 2



Как вариант - написать js функцию, которая в конце будет вызывать саму себя с setTimeout

вторник, 16 июля 2019 г.

Запрет повторной установки интервала

Есть картинка на странице. Она вращается по клику на определенный градус (через таймер). Как мне обезопаситься от дублирования таймера при повторных кликах на картинку?
Фрагмент скрипта:
var $rot = 0; var $tim3;
function rotkar($kol) { $rot = $rot + $kol; document.getElementById('kar').style.transform = "rotate(" + $rot + "deg)"; } //'kar'- это картинка
function clickar() { $tim3 = setInterval("rotkar(7);", 1000); }
function $trot() { clearInterval($tim3); }


Ответ

Можно, например, при клике проверять, есть ли ID интервала в переменной $tim3
document.addEventListener("DOMContentLoaded", function() { var $rot = 0; var $tim3; var image = document.getElementById('kar'); function rotkar($kol) { $rot += $kol; image.style.transform = "rotate(" + $rot + "deg)"; } image.addEventListener("click", function() { if ($tim3 == undefined) { $tim3 = setInterval(function() { rotkar(7); }, 1000); } }); });
Добавлять обработчик события через onclick - не лучшая затея. Передавать строку в качестве первого параметра setInterval и setTimeout - тем более.

пятница, 12 июля 2019 г.

Помощь с setInterval и setTimeout. “Карусель”

При загрузке страницы, интервал стартует как надо. Я поставил кнопку для паузы интервала, но работает не так как надо.
При клике на кнопку происходит пауза, но только на определенный срок времени, а должна быть полная пауза пока не кликну на старт. В чем проблема?
При загрузке страницы, интервал должен сразу стартовать. Я написал это, но не знаю грамотно ли.
Прошу код не менять, если нет большой необходимости. Если код поменяли, пожалуйста прокомментируйте, и если не сложно, то объясните где не грамотный код.
Спасибо.
Использовать только на JS
(function() { var elem, startInterval, removedElem, widthBlock, btn1 = document.getElementById('click1'), btn2 = document.getElementById('click2'), collectionBlocks = document.getElementById('collection_divs'); function clearThisInterval() { if (thisElem.clientWidth == 0) { removedElem = collectionBlocks.removeChild(collectionBlocks.children[0]); collectionBlocks.appendChild(removedElem); thisElem.style.width = '150px'; clearInterval(startInterval); //удаляем интервал // для следующего блока } } function minWidth() { thisElem = collectionBlocks.children[0]; widthBlock = thisElem.clientWidth; // Уменьшаем ширину if (widthBlock != 0) { startInterval = setInterval(function() { thisElem.style.width = [widthBlock -= 2] + 'px'; }, 30); } setTimeout(clearThisInterval, 2253); // 15 строка //удаляем интервал } // Запускаем интервал / строка 19 btn2.onclick = function() { setInterval(minWidth, 3000); } //становить или пауза интервала для уменьшение ширины / 23 строка // btn1.onclick = function() { clearInterval(startInterval); } //при загрузке стартует сам //setInterval(minWidth, 5000); })(); .div { width: 150px; height: 30px; background-color: red; float: left; margin-right: 2px; margin-bottom: 10px; margin-top: 10px; } button { width: 100px; height: 40px; }

1
2
3
3


Ответ

Если какой-то код, который запускает таймер, вызывается больше одного раза, он должен запоминать значение, возвращаемое setInterval, и вызывать clearInterval с этим значением перед очередным вызовом setInterval
function minWidth() { thisElem = collectionBlocks.children[0]; widthBlock = thisElem.clientWidth; // Уменьшаем ширину if (widthBlock != 0) { clearInterval(startInterval); // !!! startInterval = setInterval(function() { thisElem.style.width = [widthBlock -= 2] + 'px'; }, 30); } setTimeout(clearThisInterval, 2253); // 15 строка //удаляем интервал }
var minWidthInterval; // Запускаем интервал / строка 19 btn2.onclick = function() { clearInterval(minWidthInterval); // !!! minWidthInterval = setInterval(minWidth, 3000); }
//становить или пауза интервала для уменьшение ширины / 23 строка // btn1.onclick = function() { clearInterval(minWidthInterval); // !!! clearInterval(startInterval); }

суббота, 20 апреля 2019 г.

setInterval и задержки

День добрый, Господа! При написании скрипта столкнулся с такой проблемой: я задал переменной значение, затем я подставил эту переменную в setInterval в задержку, однако при изменении этой переменной интервал между выполнениями функции не изменялся. Возник вопрос: можно ли вообще подставить переменную как значение задержки в setInterval. Такой код есть на данный момент, передаю вам штурвал.
setInterval(ggg, 1000); var iter = 0; var pulse = 90; var time = 100; setInterval(timer, 1000); function ggg() { var aza = setInterval(ggg, 1000); setTimeout(ggg, 1000); clearInterval(aza); var aza = setInterval(ggg, 2000); }; function pulsing() { heart.style.backgroundColor = 'red'; setTimeout(back, 300); function back() { heart.style.backgroundColor = 'black'; }; }; function timer() { time--; }; Kek



Ответ

Нет, переменную как значение задержки в setInterval подставить нельзя, вот почему: setInterval выполняет код много раз через равные промежутки времени, пока он не будет остановлен вызовом clearInterval. т.е. промежуток задается один раз (при вызове setInterval).
Для того, чтобы сделать так, как вы хотите - нужно каждый раз "уничтожать" setInterval и заново создавать его, с уже новым промежутком(который есть у вас в переменной).
PS. это можно сделать разными способами, как один из возможных - при помощи Object.prototype.watch() (учитывая его не поддержку:D, можно юзать - полифилл).
var timerObj = { interval: 0, timerId: 0, func: my_function}; // объект для интервала
timerObj.watch('interval', function(prop, oldval, val) { // тут пересоздавать сам setInterval нужно: if(timerObj.timerId) clearTimeout(timerObj.timerId); timerObj.timerId = setInterval(this.func, val); });
timerObj.interval = 1000; // запустили интервал
// много кода
timerObj.interval = 5000; // в любом месте меняет, он сам пересоздается)
// можно еще придумать методы для полной остановки и т.д.
PPS. как в комментариях верно подметили - лучше использовать Object.defineProperty, тогда код выглядел бы так(полифилл не нужен):
var timerObj = {timerId: 0, func: my_function}; // объект для интервала Object.defineProperty(timerObj, 'interval', { set:function(val){ if(timerObj.timerId) clearTimeout(timerObj.timerId); timerObj.timerId = setInterval(timerObj.func, val); } });
timerObj.interval = 1000;
// много кода
timerObj.interval = 5000;

среда, 9 января 2019 г.

Повторение кода через разные промежутки времени Javascript

Здравствуйте. Мне нужно реализовать следующую логику: 1 этап: пользователи что-то делают на сервере - 40 секунд 2 этап: выполняется процесс - случайное кол-во секунд (от 3 до 10) 3 этап: кулдаун - пользователи любуются результатом - 2 секунды и все повторяется с начала и так вечно
setInterval не подходит, так как в нем код повторяется через РАВНЫЕ промежутки времени, а время окончания работы моего кода становится известно только в процессе. Если же использовать время интервала с запасом, то 3 этап будет выполняться то 2 секунды, то 15 - неприемлемо.
Такое решение (рекурсия)
function round() { var delay = 20000 * Math.random(); //узнаем, через сколько в этот раз должен сработать код setTimeout(function () { console.log('Hellow world!');//что-то тут делаю round(); //и перезапускаю }, delay); } round();
не подойдет, так как при каждой новой рекурсии будут накапливаться временные переменные и будет забиваться память, а перезагружать сервер постоянно не получится
явно ведь должно быть красивое и правильное решение? что в таком случае использовать? Нужно сделать так, чтобы была какая-то асинхронная функция с примерно таким содержанием:
-сообщить о начале 1 этапа (использую socket.io) -ждать 40 секунд -сообщить о начале 2 этапа -ждать случайное кол-во секунд -сообщить о начале третьего -ждать 2 секунды
потом функция должна запуститься заново но не рекурсией. И хотелось бы без вложенных друг в друга setTimeout. И не подобным "Войне и Миру" кодом.


Ответ

Вложеные setTimeout стек не забивают, так как выполняются асинхронно, их бояться не надо.
Для решения вашей ситуации вам надо написать самому какую-то timing микро библиотеку, позволяющую создавать цепи событий с таймаутами. Это что-то типа промисов в fetch.
Выглядеть этот код будет примерно так
TimeoutChain.PlusOne(() => { /*...*/ },2000) .PlusOne(() => { /* ещё код*/ },3000).StartChain();
Реализация будет на основе setTimeout. Но это будет выглядеть красиво, так как она инкапсулирована в эту функцию, так же из-за её асинхронности стек она не будет забивать. Так как каждая функция вызывает свой setTimeout а сама завершается.
Тут в примере пауза явно задаётся в цепи, но можно её значение просто например возвращать из самой лямбды.