Не выходит сбросить таймер, функции накладываются одна на одну

Вот мой код:

var post1, post2, post3, post4, post5;
post1 = allposts[0];
post2 = allposts[1];
post3 = allposts[2];
post4 = allposts[3];
post5 = allposts[4];
const intPost1 = () => {
  post1.className = "thumb-item";
  post2.className = "thumb-item active";
}
const intPost2 = () => {
  post2.className = "thumb-item";
  post3.className = "thumb-item active";
}
const intPost3 = () => {
  post3.className = "thumb-item";
  post4.className = "thumb-item active";
}
const intPost4 = () => {
  post4.className = "thumb-item";
  post5.className = "thumb-item active";
}
const intPost5 = () => {
  post5.className = "thumb-item";
  post1.className = "thumb-item active";
}
const slider = setInterval(function() {
  if (post1.classList == "thumb-item active") {
    setTimeout(intPost1, 5000);
  }
  if (post2.classList == "thumb-item active") {
    setTimeout(intPost2, 5000);
  }
  if (post3.classList == "thumb-item active") {
    setTimeout(intPost3, 5000);
  }
  if (post4.classList == "thumb-item active") {
    setTimeout(intPost4, 5000);
  }
  if (post5.classList == "thumb-item active") {
    setTimeout(intPost5, 5000);
  }
}, 0);
  allposts.forEach((thumbPost) =>
  thumbPost.addEventListener('click', () => {
    clearTimeout(intPost1);
    clearTimeout(intPost2);
    clearTimeout(intPost3);
    clearTimeout(intPost4);
    clearTimeout(intPost5);
    for (i = 0; i < allposts.length; i++) {
      allposts[i].className = "thumb-item";
    }
    thumbPost.className = "thumb-item active";
  })
);

Как остановить таймеры?


Ответы (2 шт):

Автор решения: SwaD

В вашем коде много "недочетов", проще переписать его.

Т.к. у вас есть массив с нужными DOM узлами, надо просто в цикле проходить по данному массиву раз в N времени и выполнять нужные действия.

Что бы была возможность остановить интервал или таймаут, его id надо сохранить в переменную(setInterval и setTimeout возвращают свой id)

Так же запуск setInterval(() => {}, 0) с 0 задеркой приводит к тому, что интервал выполняется, условно, всегда(кладет себя на выполнение в event loop, как только отрабатывает, тут же добавляется еще раз. Задержка, ну 10-30мс)

// Текущий индекс элемента
let currentIndex = 0;
// ID таймера
let timer;
// Это массив с нашими DOM узлами
const allPosts = document.querySelectorAll('.thumb-item');

function changeActiveElement() {
  // Запускаем таймер. Сработает через 1000 мс(1 секунда)
  timer = setTimeout(() => {
    // Убираем у текущего активный класс
    allPosts[currentIndex].classList.remove('active');
    // Проверяем, что не вышли за пределы массива
    if (currentIndex === allPosts.length - 1) currentIndex = 0; // вышли, ставим первый
    else currentIndex++; // Не вышли, увеличиваем
    // Устанавливаем следующему элементу активный класс
    allPosts[currentIndex].classList.add('active');
    // Запускаем заново функцию
    changeActiveElement();
  }, 1000);
}
// Кнопка запуска
document.getElementById('sing').addEventListener('click', changeActiveElement);
// Устанавливаем обработчик клика по остановке таймера
allPosts.forEach(div => div.addEventListener('click', () => clearTimeout(timer)));
.thumb-item {
  background-color: #e8e8e8;
  width: 300px;
}

.active {
  background-color: #4aff67;
}

.singList {
  display: inline-table
}
<div class="singList">
  <div class="thumb-item active">Раз ромашка</div>
  <div class="thumb-item">Два ромашка</div>
  <div class="thumb-item">Три ромашка</div>
  <div class="thumb-item">Смотри, песенка получается</div>
  <div class="thumb-item">Пять ромашка</div>
  <div class="thumb-item">Шесть ромашка</div>
  <div class="thumb-item">Семь...</div>
  <!-- <div class="thumb-item">А ты четвертую сорвал? Давай с начала</div>
  <div class="thumb-item">Раз ромашка</div>
  <div class="thumb-item">Два ромашка</div>
  <div class="thumb-item">Три ромашка</div>
  <div class="thumb-item">А я четвертую сорвал</div>
  <div class="thumb-item">Пять ромашка</div>
  <div class="thumb-item">Шесть ромашка</div>
  <div class="thumb-item">Семь...</div>
  <div class="thumb-item">Восемь, девять, десять...</div> -->
</div>
<button id="sing">Споём?</button>

Ну и про var стоит уже давно забыть

→ Ссылка
Автор решения: Nikita Mokhynia

Спасибо всем за помощь в итоге получилось так:

let currentIndex = 0;
let timer;
// Массив
const allThumb = document.querySelectorAll('.thumb-item');

function changeActiveElement() {
  timer = setTimeout(() => {
    allThumb[currentIndex].classList.remove('active');
    if (currentIndex === allThumb.length - 1) currentIndex = 0;
    else currentIndex++;
    allThumb[currentIndex].classList.add('active');
    changeActiveElement();
  }, 5000);
}
// Запуск
window.addEventListener('load', changeActiveElement);
// Смена по клику
allThumb.forEach((post, index) => post.addEventListener('click', () => {
  clearTimeout(timer)
  for (i = 0; i < allThumb.length; i++) allThumb[i].classList.remove('active');
  post.classList.add('active');
  currentIndex = index;
  changeActiveElement();
}));

→ Ссылка