Basic JS/TS Question

I know this isn’t Phaser specific, but you peeps are a great community. I have an odd problem that I’m going to try to boil down to one line.

When I log this object with this line of code:
console.log({board: board, sectorCount: board.sectorCount})

I get this result in the browser.

`

board: GameBoard
    columns: 1000
    rows: 100
    sectorCount: 100
    sectorSize: 10
sectorCount: undefined

`

Notice when I print the ‘board’ object the ‘sectorCount’ = 100… but when i print ‘board.sectorCount’ the value is undefined.

Am I going crazy? It’s 1:15 am…

Hi :wave:t2:, I don’t know but for me looks like board is instantiated from the class GameBoard which maybe has a getter for returning the values. So, my guess is try:
console.log({board: board, sectorCount: board.get().sectorCount})

Thanks @Darko, I played around with your idea to no avail. I even tried to make a getSectorSize(): integer method… but that also returned undefined.

Maybe some more information would help… This is the Typescript class that I made that defines the GameBoard class. I wonder if it is because it is an async method?

export class GameBoard extends Phaser.Events.EventEmitter {
    columns: integer
    rows: integer
    sectorSize: integer
    sectorCount: integer
    sectors: GameSector[]

    constructor(private api: NetworkInterface) {
        super()
        this.api.on(NetworkEventCellUpdateName, (update: NetworkEventCellUpdate) => {
            this.onCellUpdateFromNetwork(update)
        })
    }
//...

  private async initializeBoardData(): Promise<void> {
        console.log({
            board: this,
            sectorCount: this.sectorCount,
        })
       //...
    }
//...
}

SOLVED (sort of)

Well I think I solved it… but I’m not sure how. The sectorCount is initialize by the response to another http call. Apparently using await to get the response and set the value works better than working directly with the Promise. It must be some magic scoping issue I am not seeing right now.

    // BAD
    private async initializeMetaData(): Promise<void> {
        this.api.GetBoard().then((resp) =>{
            console.log(resp)
            this.rows = resp.sectorRows * resp.sectorSize
            this.columns = resp.sectorCount * resp.sectorSize
            this.sectorCount = resp.sectorCount
            this.sectorSize = resp.sectorSize
            this.sectors = [] as GameSector[]
        }).catch((error) => {
            console.log(`getFullBoard(): ${error}`)
        })
    }

    // GOOD
    private async initializeMetaData(): Promise<void> {
        const resp = await this.api.GetBoard()
        console.log('resp: ', resp, resp.sectorSize)
        this.rows = resp.sectorRows * resp.sectorSize
        this.columns = resp.sectorCount * resp.sectorSize
        this.sectorCount = resp.sectorCount
        this.sectorSize = resp.sectorSize
        this.sectors = [] as GameSector[]
    }
1 Like

In the first snippet, initializeMetaData just sets up a Promise without doing anything with it. The method will return immediately and because it is async, its return value will be a Promise resolved to undefined. The handler for GetBoard will run after initializeMetaData's Promise has been resolved.

In the second snippet, the GetBoard Promise is awaited before being used. The initializeMetaData method will pause its execution at the await line and continue when the data becomes available. Only after that will the Promise (implicitly) returned by it resolve.

You can fix the first snippet in two ways. The cleaner one is to return the entire expression involving GetBoard (in this case, the method doesn’t even have to be async because you’re not await-ing anything and you’re returning a Promise anyway). You technically could also await the same expression, but there’s no reason to do so and it could cause problems with error handling.

If you want to use an async function, use the second snippet. The first snippet has no reason to be async if you return the Promise.

2 Likes

Thank you for the detailed explanation. That makes total sense.