Alex Lofnes
Alex Lofnes

Reputation: 53

Svelte bubble sort visualization wont update dom

I want to make a bar visualisation of many sorting algorithms, I started will bubble sort for simplicity sake. I need to update the dom as it switches the items, but it only updates it after all the elements are sorted. I looked this up and everything said to use tick, but I still can't get it to work, here is my code:

<script>
    import { tick } from 'svelte';
    let arr = [];

    async function bubbleSort () {
        let len = arr.length;
        for (let i = 0; i < len; i++) {
            for (let j = 0; j < len; j++) {
                if (arr[j] > arr[j + 1]) {
                    let tmp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = tmp;
                    await tick();
                    setTimeout(() => {  console.log("World!"); }, 2000);
                }
            }
        }
        console.log(arr)
    }

    function shuffle () {
        arr = [];
        for (let i = 0; i < 100; i++) {
            let num = Math.random()*10+1;
            arr.push(Math.floor(num));
        }
        console.log(arr)
    }
    console.log(bubbleSort(shuffle()))
</script>

<main>
    <button on:click={shuffle}>Shuffle</button>
    <button on:click={bubbleSort}>Sort</button>
    {#each arr as el, i}
        <div id={i} style="position: relative;height: {el*100}px;"></div>
    {/each}
</main>

<style>
    div {
        background: #000000;
        width: 5px;
        display: inline-block;
        margin: 0 1px;
    }
</style>

I am sorry if this is simple but I am very new to svelte, js and web dev as a whole. Thank you!

Upvotes: 3

Views: 95

Answers (1)

BenVida
BenVida

Reputation: 2312

Here's the fixed script:

<script>
    let arr = [];
    
        function sleep(time){
             return new Promise((resolve, reject) => {
                setTimeout(() => {
                        resolve();
            }, time);
            }); 
        }

    async function bubbleSort () {
        let len = arr.length;
        for (let i = 0; i < len; i++) {
            for (let j = 0; j < len; j++) {
                if (arr[j] > arr[j + 1]) {
                    let tmp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = tmp;
                    await sleep(1)
                }
            }
        }
        console.log(arr)
    }

    function shuffle () {
        arr = [];
        for (let i = 0; i < 100; i++) {
            let num = Math.random()*10+1;
            arr.push(Math.floor(num));
        }
        console.log(arr)
    }
    console.log(bubbleSort(shuffle()))
</script>

<main>
    <button on:click={shuffle}>Shuffle</button>
    <button on:click={bubbleSort}>Sort</button>
    {#each arr as el, i}
        <div id={i} style="position: relative;height: {el*100}px;"></div>
    {/each}
</main>

<style>
    div {
        background: #000000;
        width: 5px;
        display: inline-block;
        margin: 0 1px;
    }
</style>

The sleep function is based on the code found in the MDN documentation about promises: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise#chained_promises

It's actually not so easy to do a sleep in Javascript because it's designed to never stop running.

You will probably need to study up on how the promises and async - await works to understand why this works.

BTW, your code did update the DOM but it ran through in a split second because there was very little delay. The tick method that you used stops the script only until the DOM update finished based on the previous changes - which is usually a very, very short time.

Upvotes: 2

Related Questions