Кстате, наглядно и доходчиво про EventLoop(
Хабр)
И да, подкатом говнокод страшенный, но вынос вторичной перекраски кнопки в Macrotask(через requestAnimationFrame) сделал свое дело
Это говнокод, я предупреждал
document.addEventListener('DOMContentLoaded', () => {
const testItem = document.getElementById('test')
const testBtn = document.getElementById('test-btn')
const sleep = async function(tau) {
let t0 = performance.now()
const tEnd = t0 + tau
return new Promise((resolve) => {
let i = 0
while(true) {
if(i++ === 100) {
i = 0
t0 = performance.now()
if(t0 >= tEnd) {
break
}
}
}
resolve(true)
})
}
const redraw = function(cl) {
testItem.style.color = cl
}
testBtn.addEventListener('click', async () => {
requestAnimationFrame(() => {
redraw('red')
requestAnimationFrame(async () => {
console.log('>>')
await sleep(2000)
console.log('>> >>')
await sleep(2000)
console.log('>>>> >>>>')
redraw('blue')
})
})
})
})
Upd. суть задачи в имитации setTimeout через цикл while без использования таймаутов с ненулевой задержкой