Reputation: 53
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
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