what about delaying the reading of the target.attribute value with setTimeout, works rather consistently for me:
const observer = new MutationObserver(records => {
for (const record of records) {
if (record.type !== 'attributes') continue
setTimeout(
function(delayedRecord) {
handleAttributeChange(
delayedRecord.attributeName!,
delayedRecord.oldValue,
delayedRecord.target.attributes.getNamedItem (delayedRecord.attributeName).value
)
}, 0, record )
}
})
I've found that setting the timeout delay for 0ms runs the code in the next tick - usually when the attribute value has been updated.