3

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!

  • Swapping the ```await tick(); setTimeout(() => { console.log("World!"); }, 2000);``` with ```await new Promise((r) => setTimeout(r, 200));``` works for me, though I have no idea what the await new Promise((r) => setTimeout(r, 200)); does – Alex Lofnes Dec 16 '21 at 07:31
  • see: [What is the JavaScript version of sleep()?](https://stackoverflow.com/questions/951021/what-is-the-javascript-version-of-sleep) – pilchard Dec 16 '21 at 08:34
  • @AlexLofnes I posted a solution for you and I believe it does fix the problem and even provides explanation with a reference link. Would you mind marking my answer as accepted? Much appreciated! – BenVida Dec 18 '21 at 06:41

1 Answers1

2

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.

BenVida
  • 1,796
  • 1
  • 16
  • 25