That's because your task never finishes so that micro task never gets to run. Micro tasks run when a (any) task has been completed.
You see that is quite an antipattern. You also don't have any kind of throttling there. Even if it wasn't flawed due to the micro tasks stuff, it would be extremely CPU intensive and print hundred of thousands of times per second.
There is a couple ways though, setinterval or requestAnimationFrame come to mind.
Simple example / pseudo code for setInterval. Assuming you have a declared and initialized with true and set it to false at some point like you have shown.
let a = true
setTimeout(()=>{
a = false
},2000)
let interval = setInterval(() => {
If (!a) {
clearInterval(interval)
return
}
console.log("looping")
}, 0)
I recommend watching this https://youtu.be/cCOL7MC4Pl0
let a = true setTimeout(()=>{ a = false },2000) let prevTime = Date.now(); while(a){ console.log('While Loop'); if(Date.now() - prevTime > 2000){ a = false; console.log('Loop finished') } }