I seem to be encountering a race condition with a function of mine even though I am not using async functions in it
window.focusElem = (elem, overrideGroupNextFocus) => {
if (!elem) return
console.log(`FOCUS: ${elem.id}`)
if (store.getState().app.isExitVisible &&
elem.id !== 'exitExitButton' &&
elem.id !== 'exitBackButton'
) {
return
}
// Remove focus class from existing focused elements
Array.from(document.querySelectorAll('.focus')).forEach(e => {
console.log(`FOCUS: ${elem.id} removing focus from ${e.id}`)
e.classList.remove('focus')
})
const parentFocusGroup = findParentFocusGroup(elem)
let elemToFocus = elem
const focusGroupNextFocusId = parentFocusGroup ? parentFocusGroup.getAttribute('data-focusgroup-next-focus') : ''
if (!overrideGroupNextFocus &&
focusGroupNextFocusId &&
document.activeElement.id !== focusGroupNextFocusId) {
elemToFocus = parentFocusGroup.querySelector(`#${focusGroupNextFocusId}`) || elem
}
store.dispatch(setFocusElem(elemToFocus.id))
if (elemToFocus.id.startsWith('appNav')) {
Array.from(document.querySelectorAll('.active')).forEach(e => e.classList.remove('active'))
elemToFocus.classList.add('active')
document.querySelector('.app-wrapper').setAttribute('data-sidebar', 'open')
} else if (!elemToFocus.hasAttribute('data-focus-inmodal')) {
document.querySelector('.app-wrapper').setAttribute('data-sidebar', 'closed')
}
lastFocused = elemToFocus
console.log(`FOCUS: ${elem.id} add focus to ${elemToFocus.id}`)
elemToFocus.classList.add('focus')
document.dispatchEvent(new CustomEvent('app:focusChanged', { detail: elemToFocus }))
}
function findParentFocusGroup(elem) {
if (elem.hasAttribute('data-focusgroup')) {
return elem
}
const parent = elem.parentNode
if (parent && parent.nodeType !== 9) return findParentFocusGroup(parent)
}
I notice if this function is called in fast succession, I can get the following output in console:
FOCUS: history0
FOCUS: history0 removing focus from vodBannerProgram
FOCUS: vodBannerProgram
FOCUS: vodBannerProgram add focus to vodBannerProgram
FOCUS: history0 add focus to history0
Notice, it seems like this function is called for history0
first then vodBannerProgram
. But it seems like it executed halfway for history0
then proceeded to vodBannerProgram
then back again? forEach
are synchronous correct?