I wonder if you would be able to help me. I have a function that removes all items in a cart, the code (while loop) works, but I want to remove one at a time, with a visible delay (say 200ms).
It looks like an IIFE would be the way to go with a setTimeout function, but I can’t get it to work. Any ideas? – N.B. My failed attempts are commented out.
Is there any particular technical reason you want it to be delayed, besides the visual aspect?
I say so since JS is by nature a synchronous language and manually force async generally involves some tweaking.
The easiest approach would be increasing the timeout based on a loop condition (usually index)
for(let i = 0; i < 3; i++) {
setTimeout(myFunc, i *10)
}
// the program generates a stack of 3 function delayed by 0, 10, 20 ms
A more robust approach would probably involve wrapping the delete function inside a Promise and then call each only after the previous Promise resolve.
This will easily lead to the so called callback-hell.
However if the reasoning behind this is purely visual, you don’t really need to turn a sync function into an async one, you can simply use a delayed css animation to give the “impression” of a one by one action.
Thanks for you comments, and yes, it was just for the visual aspect. However, ideally I would have wanted the sub-total to update. I couldn’t get the delayed css animation to work, so I did the delay using javascript. I probably could have done it with promises, but that would have added complexity.
I ended up at an acceptable solution using two loops and timeouts (one to add a css class and the other to remove the element). You can see the project here (note, this project was originally forked from john-smilga).
Here is the function:
removeAll() {
let numItems = this.cart.childElementCount-2; /* Minus two because the buttons are elements too */
for (let i = 0; i<numItems; i++) {
setTimeout(() => { this.cart.children[i].classList.add('empty-cart'); }, i*50)
}
setTimeout(() => {
while (this.cart.childElementCount > 2) {
this.cart.removeChild(this.cart.children[0]);
}
showTotals();
this.showCart();
}, numItems * 50);
}