0

I am trying to select elements in the loop and pass them to setTimeout.

Why doesn't the following work as it is supposed to?

Is it because el.querySelector('.b') is slower than setTimeout?

var ids = document.querySelectorAll('.a'),
  span

ids.forEach(el => {

  span = el.querySelector('.b')
  setTimeout(function() {
    span.classList.add('visible');
  }, 20, span);
})
.visible{
  color:red;
}
<p class="a"><span class="b">1</span></p>
<p class="a"><span class="b">2</span></p>
<p class="a"><span class="b">3</span></p>
Konrad
  • 21,590
  • 4
  • 28
  • 64
Toniq
  • 4,492
  • 12
  • 50
  • 109

2 Answers2

2

Just don't use var and declare variables in their scope

const ids = document.querySelectorAll('.a')

ids.forEach(el => {
  const span = el.querySelector('.b')
  setTimeout(function() {
    span.classList.add('visible');
  }, 20);
})
.visible {
  color: red;
}
<p class="a"><span class="b">1</span></p>
<p class="a"><span class="b">2</span></p>
<p class="a"><span class="b">3</span></p>
Konrad
  • 21,590
  • 4
  • 28
  • 64
  • 1
    What sense does it make to pass `span` as third argument to `setTimeout`, if the callback function does not have any arguments? The `span` in `span.classList` is referring to the `const span` from the outer scope ... – derpirscher Dec 05 '22 at 09:46
2

In the code you provided, the span variable is overwritten on each iteration of the forEach loop, so when the callback function is executed, it will always reference the same element (the last one selected by querySelector). To fix this, you can move the querySelector call inside the callback function, like this:

var ids = document.querySelectorAll('.a'),
  span
  
ids.forEach(el => {
  setTimeout(function() {
    var span = el.querySelector('.b')
    span.classList.add('visible');
  }, 2000);
})
.visible{
  color:red;
}
<p class="a"><span class="b">1</span></p>
<p class="a"><span class="b">2</span></p>
<p class="a"><span class="b">3</span></p>

This should work as expected. I've increased the delay to make the change more visible.

Felix G
  • 724
  • 5
  • 17
  • Third parameter is supported: https://stackoverflow.com/questions/1190642/how-can-i-pass-a-parameter-to-a-settimeout-callback – Toniq Dec 04 '22 at 15:03