Вопрос

I have a bubble sort function that when the a swap occurs it should show it visibly. But after lots of approaches it continues executing the loops without waiting for the animation to stop. (we are only allowed to use JavaScript). Is there a way to tell the website to wait for the animation to complete. Here is a snippet of my code:

for (var i = 0; i < len; i++) 
{

    for (var j = 0, swapping, endIndex = len - i; j < endIndex; j++) 
    {
        if (marksArr[j] > marksArr[j + 1]) 
        {
            //swap objects




            /*(function() {
                var k = 0,
                    action = function() {
                        document.getElementById(coursesKey[j]).style.top = (parseInt(document.getElementById(coursesKey[j]).style.top) + 1) + 'px';
                        document.getElementById(coursesKey[j + 1]).style.top = (parseInt(document.getElementById(coursesKey[j+1]).style.top) - 1) + 'px'; 

                        k++;
                        if (k < difMoves) {
                            setTimeout(action, 200);
                        }
                    };

                setTimeout(action, 200);
            })();*/



        }
    }
}
Это было полезно?

Решение

As @cookie monster already explained, you can't block loops in JavaScript and update the UI using setTimeout() at the same time (this is because JavaScript is essentially single-threaded).

The most elegant solution would be "recording" each animation step while the for loops process the array, and then run the animation afterwards, e.g. using setTimeout(). Some time ago, I've implemented this approach for a similar question on StackOverflow; here's a demo: JSFiddle

The code can also be simplified:

function swap(list, i1, i2) {
    var tmp = list[i1];
    list[i1] = list[i2];
    list[i2] = tmp;
}

function animateBubblesort(list) {
    var animationSteps = [];

    // Sort array
    for (var n = list.length; n > 1; --n) {
        for (var i = 0; i < n-1; ++i) {
            if (list[i] > list[i+1]) {
                swap(list, i, i+1);
                // Add new step (clone of current array) to "animation queue"
                animationSteps.push(list.slice(0));
            }
        }
    }

    // Print animated steps (using setInterval() for simplicity)
    var count = 0, 
        interval = setInterval(function(){
            console.log(animationSteps[count]);
            if (++count >= animationSteps.length) {
                clearInterval(interval);
            }
        }, 250);
}

animateBubblesort([5,8,2,4,1,9,7,3,0,6]);

DEMO

Another (less intuitive) possibility would be to implement the algorithm without loops in order to get control over when the next step of the algorithm is executed (so you have time for your animation). Here's an example: DEMO 2

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top