0

there! I've been trying to use two variables on my code (total and soldTickets) but they're not being summed up or show the correct value. I think it's something related with the scope. console.log() returns 0 and [], respectively.

class SaleController {

    constructor() {
        this.Sale = require('../models/Sale')
        this.Show = require('../models/Show')
    }

    buyTickets(req, res) {
        const json = req.body

        let soldTickets = []
        let total = 0

        json.tickets.forEach(ticket => {

            for (let i = 0; i < ticket.qty; i++) {

                this.Show.findById(ticket.showId, 'sectors', (err, shows) => {
                    if (err) return res.status(500).json({
                        status: 'failed',
                        message: 'Something happened while finding the show!'
                    })

                    const foundTicket = shows.sectors.find(sector => sector.name === ticket.sector)
                    total += foundTicket.price

                    soldTickets.push({
                        number: this.generateTicketNumber(),
                        showId: ticket.showId,
                        sector: ticket.sector,
                        price: foundTicket.price
                    })
                })

            }

        })

        console.log(total)
        console.log(soldTickets)

        res.json({
            tickets: soldTickets,
            total: total
        })
    }

    generateTicketNumber() {
        return Math.floor(Math.random()*90000) + 10000
    }
}

module.exports = new SaleController()
  • This has nothing to do with scope. You're making async calls to the database which will return later. After your res.json call is done. The callback you're providing is called once it get the value. – ayushgp Feb 12 '18 at 14:06

1 Answers1

0

The problem is that you are setting the variable in a callback function. This has nothing to do with the scope, but with the execution order instead.

You need to wait for the last callback to finish before doing anything with the total or soldTickets variable.

So you know the number of requests your doing (ticket.qty). You can now just check inside the callback function if this was the last request. If it was, you can return both values.

class SaleController {

    constructor() {
        this.Sale = require('../models/Sale')
        this.Show = require('../models/Show')
    }

    buyTickets(req, res) {
        const json = req.body

        let soldTickets = []
        let total = 0

        json.tickets.forEach(ticket => {

            for (let i = 0; i < ticket.qty; i++) {

                this.Show.findById(ticket.showId, 'sectors', (err, shows) => {
                    if (err) return res.status(500).json({
                        status: 'failed',
                        message: 'Something happened while finding the show!'
                    })

                    const foundTicket = shows.sectors.find(sector => sector.name === ticket.sector)
                    total += foundTicket.price

                    soldTickets.push({
                        number: this.generateTicketNumber(),
                        showId: ticket.showId,
                        sector: ticket.sector,
                        price: foundTicket.price
                    })

                    // If it was the last request
                    if (i === ticket.qty - 1 && json.tickets.indexOf(ticket) === json.tickets.length - 1) {
                      // Log values
                      console.log(total)
                      console.log(soldTickets)

                      // send response
                      res.json({
                        tickets: soldTickets,
                        total: total
                      })
                    }

                })

            }

        })
    }

    generateTicketNumber() {
        return Math.floor(Math.random()*90000) + 10000
    }
}

module.exports = new SaleController()

Please note that this code is untested.

Maybe you run into some problem when the second last request takes longer than the actual last. Therefore I would recommend to build a counter that measures how many requests already came back. After the last request, it should respond the values.

Larce
  • 841
  • 8
  • 17