简体   繁体   中英

Why doesn't setTimeout() work in my sorting function?

UPDATE I could not figure out what the problem was to this, but I found a solution to my overall problem. I simply changed my bubbleSort() algorithm to only utilize for-loops and that appeared to work. Thank you for the help!

I am currently learning javaScript and React. As a practice project, I am attempting to create a sorting algorithm visualizer. For a (what I thought would be a simple) warmup, I have implemented bubble sort first, using a psuedocode I found online. I had it so the array sorts and changes on screen, but it was too fast so it didn't show the actual animation for the process on how it got to that point. In order to do that I would need to delay each iteration of the loops in the algorithm. However, my implementation is acting strange. The display animates the first iteration being sorted, then suddenly stops. The algorithm seems to quit early instead of finish the whole process when I add setTimeout() to my function. To finish the whole sorting process you need to repeatedly press the button until every single item is sorted. Nothing I try seems to work, and I would be very grateful if anyone could explain why and maybe offer some help.

bubbleSort() {
        var arr = this.state.array
        var isSorted = false
        var lastUnsorted = arr.length - 1
        while (!isSorted) {
            isSorted = true;
            for (let i = 0; i < lastUnsorted; ++i) {
                setTimeout(() => {
                    if (arr[i] > arr[i + 1]) {
                        swap(arr, i, i + 1)
                        isSorted = false
                    }
                    this.setState({ array: arr })
                }, i * 1);
            }
            lastUnsorted--
        }
        this.setState({ array: arr })
    }

setTimeout is asynchronous, but your code doesn't wait for it to resolve, so it calls setTimeout for lastUnsorted times, so all the timeouts happen at the same time.

You need to controll it with callbacks.

The setup below will cause the console.log('tick') to happen every 1 second for 5 seconds.

 const functionToRepeat = () => { console.log('tick') } const loopWithCallback = (callback, i, limit) => { if(i > limit) return setTimeout(()=>{ callback(loopWithCallback(callback, i+1, limit)) }, 1000) } loopWithCallback(functionToRepeat, 1, 5)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM