(This is an edited question, based on Adam H's help.)
I have a complex web-app in Javascript. Some actions are lengthy, and I want to show the busy cursor during these actions. These actions take on many forms, in many places in the code. They inspect, modify and rearrange the DOM, and often add event handlers.
I want to use a wrapper-function. The wrapper should show the busy cursor, execute the wrapped function, then revert the cursor to normal. Simplified, it looks like this:
function lengthy1(func) {
document.body.classList.add('waiting');
document.getElementById('notice').innerText = 'waiting';
window.setTimeout(() => {
func();
document.body.classList.remove('waiting')
document.getElementById('notice').innerText = 'done';
}, 0); // Zero delay is unreliable, but works almost always with 100 msec
}
function lengthy2(func) {
document.body.classList.add('waiting');
document.getElementById('notice').innerText = 'waiting';
new Promise((resolve, reject) => {
func();
resolve();
}).then(() => {
document.body.classList.remove('waiting')
document.getElementById('notice').innerText = 'done';
});
}
function LongAction() {
// First add many paragraphs...
for (let i = 0; i < 20000; i++) {
const para = document.createElement('p');
para.innerText = `This is paragraph ${i}`;
para.classList.add('asdf');
document.body.appendChild(para);
}
// ... then remove them again.
let matches = document.getElementsByClassName('asdf');
while (matches.length > 0) matches[0].remove();
}
function butt1() {
lengthy1(LongAction);
}
function butt2() {
lengthy2(LongAction);
}
body.waiting * {
cursor: wait !important;
}
<body>
<span id='notice'>xxx</span><br>
<button onClick='butt1();'>Button 1</button>
<button onClick='butt2();'>Button 2</button>
</body>
Function lengthy1() is my original attempt. This works often but not nearly always, and works more often when the delay is increased (!).
Function lengthy2() is rephrased from Adam H. This works fine in Adam H's version, but not in my rewritten version.
What would be the best way to reliably change the cursor during a lengthy operation?
Use promises.
Second Solution
Use both a promise and setTimeout.