aleksander frnczak
aleksander frnczak

Reputation: 449

stop executing the loop until the function is completed

I'm trying to build a simple game in React and I need to make an animation where a set of blocks change their color to orange for 1 sec and go back to white. This operation needs to happen one by one.

Here is my game with an array of divs:

this is my game with an array of divs

And let's say the array is [1,3,5,6] I want to loop through that array and add a class with bg color to each div for a second and then removed it

I tried many things but the close I can get I that all the divs change their color at the same, not one by one

this is my code with a function that is starting by pressing "next lvl" and another async function

const displayBlocks = async (key) => {  
    let promise = new Promise((res,rej) => {
        setTimeout(() => {
                divArray.classList.remove('active');
                res('color removed');
            }, 500)
        });
        console.log(key);
        ref.current.childNodes[key].classList.add('active'); 
        let result = await promise;     
        return result;          
}

const handleNewGame = () => {
    blockArray = []
    // generate array with random cells according to points
    for (let i = 0;i< props.points;i++) {
        let key = Math.floor(Math.random() * (props.board.length)) + 0;
        displayBlocks(key).then((res) => {
            console.log(res);
            blockArray.push(key);
        })                   
    }
    console.log(blockArray);
}

I tried many solutions with async or without but none of them worked. Can you tell me how can I stop the execution of the loop until the displayBlock functions are completed?

Upvotes: 1

Views: 1181

Answers (2)

Suman Barick
Suman Barick

Reputation: 3411

If you share the full working code in some online code editor I can fix it, but for now, I will share some pseudo code that you can convert into real code.

The idea is, if you want your divs change color 1 by 1, then add the class also one by one, keep track of the time in your calculation. See the pseudo code below,

function displayBlock (index) {
    let duration = 1000
    let waitTime = index * duration
    let thisDiv = divArray[index]

    // Now wait for waitTime amount of time before adding the OrangeClass
    setTimeout(() => {
        thisDiv.addClass('OrangeClass')

         //Now from this point, wait for another 1 sec and remove the OrangeClass
         setTimeout(() => {
             thisDiv.removeCLass('OrangeClass')
         }, duration)

    }, waitTime)

}

If you can perfectly implement it, it should work as per your expectation. Just do some trial and error.

You can do it. Cheers :)

Upvotes: 0

Ferenc
Ferenc

Reputation: 537

Note: Can't test it at the moment, might run into the same problem

Your displayBlocks method is not awaitable. Have you tried something like

const displayBlocks = async (key) => {  
                return new Promise((res,rej) => { // return with promise to make it awaitable
                    setTimeout(() => {
                            divArray.classList.remove('active');
                            res('color removed');
                        }, 500)
                    });
                    console.log(key);
                    ref.current.childNodes[key].classList.add('active'); 
                    let result = await promise;     
                    return result;          

    }


    const handleNewGame = () => {
        blockArray = []
        // generate array with random cells according to points
        for (let i = 0;i< props.points;i++) {
            let key = Math.floor(Math.random() * (props.board.length)) + 0;
            var res = await displayBlocks(key); // await should halt the loop
            console.log(res);
            blockArray.push(key);                               
        }
        console.log(blockArray);
    }

Upvotes: 1

Related Questions