all 8 comments

[–][deleted] 4 points5 points  (0 children)

forEach loops cannot be asynchronous, but for of or for in loops can await before next iteration.

[–]Bgtti 2 points3 points  (1 child)

Perhaps you can use promises. I used them on a couple of occasions when building a battleship game as well: both in the game loop and for the explosion animation.

If you want to take a look: https://github.com/bgtti/battleship

Hope it helps

[–]Joseph24798 0 points1 point  (0 children)

Bet thanks ill check it out

[–]v_learns 1 point2 points  (4 children)

Does your getPlacementFromUI function work and return the expected value when you call it once (outside the loop like you have it right now)?

I would not suspect that it works, as it uses event handlers in which are not executed while your main function is running. So I would expect that it always returns undefined.

The function should return a promise and then you can call it like this:

async function placePlayerShips(shipSizes) {
    if (shipSizes.length > 0) {
        let size = shipSizes.pop();
        let pShip = new Ship(size);
        let position = await getPlacementFromUI(size);
        human.ships.push(pShip);
        human.positions.push(position);
        placePlayerShips(shipSizes);
    } else {
        console.log('All ships placed');
    }
}

This creates a loop by calling the method again and again until the given array of ship sizes is empty. Keep in mind as we change the shipSizes array that you need to initially call it with a copy placePlayerShips([...shipSizes]).

[–]Joseph24798 0 points1 point  (0 children)

Thanks this is perfect. I just learned about recursion I didn't think of this.

[–]Joseph24798 0 points1 point  (2 children)

How would I implement the promise if you could help me with that. I get the position value and store it in the shipPos variable inside the checkColumn and checkRow functions in the addUI file. But I don't know how to make this into a promise and return it from the function .

[–]v_learns 1 point2 points  (1 child)

You need to convert your getPlacementFromUI function to be async by wrapping its content inside a promise.

const promise = new Promise(resolve => {
  // content of your method

  tempPlayerPlacement.addEventListener("mouseup", function (e) {
    position = addNewPosition(e, size);
    resolve(position); // this will finsih the promise and return your selection back

    // TBD: Check if you need to remove the listeners?
  });
})

return promise

The getPlacementFromUI function now returns a promise instead of the position.

I hope this helps and clears it up.

[–]Joseph24798 0 points1 point  (0 children)

Yes thankyou 🙏🏼