Colfah
Colfah

Reputation: 358

Promise.all won't work for two mongodb queries

I am trying to merge three pieces of data at the backend into one array of objects. I am trying to figure out whether there are sufficient tickets available to proceed with the sale. The three pieces of data are:

  1. A request from the front end to purchase a certain number of a certain type of ticket for an event. This is an array of objects.

  2. The total number of tickets of that type for that event that have already been sold.

  3. The number of tickets of that type that are available to sell from the the Event Document I created in MongoDB.

This is working using the following code. However, it is synchronous and I would like to do it asynchronous to speed up the site.

let numTicketsSought = req.body.numTicketsSought.map(e => { return(

    Ticket.find({
        userEvent: req.body.userEvent,
        ticketTypeID: e.ticketTypeID
    }).lean().countDocuments()
    .then(number => {
        e.ticketsSold = number
        return e
    }))

}) 

Promise.all(numTicketsSought).then(numTicketsSoughtdata => {
    Event.findById(req.body.userEvent)
        .lean()
      .then(eventdata => {
            numTicketsSoughtdata.map(e => {return (
                eventdata.tickets.forEach(f => {
                    if (e.ticketTypeID === f.ticketTypeID){
                        e.numberOfTickets = f.numberOfTickets
                        e.ticketsAvailable = e.numberOfTickets - e.ticketsSold
                        return e
                    }
                })
            )})

})

However, when I try to run Ticket.find and Event.findbyID asynchronously (using Promise.all) the code won't run. Here is the code:

    let numTicketsSought = req.body.numTicketsSought.map(e => { return(

    Ticket.find({
        userEvent: req.body.userEvent,
        ticketTypeID: e.ticketTypeID
    }).lean().countDocuments()
    .then(number => {
        e.ticketsSold = number
        return e
    }))

})

let eventInfo = Event.findById(req.body.userEvent).select('tickets.ticketTypeID tickets.numberOfTickets')
    .then().catch(err => console.log(err))

    Promise.all([numTicketsSought, eventInfo]).then(data => {
let numTicketsSought = data[0]
let eventInfo = data[1]
console.log('numTicketsSought', numTicketsSought)
console.log('eventInfo', eventInfo)
numTicketsSought.map(e => {return (

                eventInfo.tickets.forEach(f => {
                    console.log('TRIGGERED')
                    console.log('e.ticketTypeID ', e.ticketTypeID )
                    console.log('f.ticketTypeID ', f.ticketTypeID )
                    console.log('----------------')
                    if (e.ticketTypeID === f.ticketTypeID){
                        console.log('MATCHED')
                        e.numberOfTickets = f.numberOfTickets
                        e.ticketsAvailable = e.numberOfTickets - e.ticketsSold
                        return e
                    }
                })
            )})

})

This is what the terminal is showing:

numTicketsSought [ Promise {
    { ticketType: 'Early Bird',
      ticketTypeID: 1,
      numTicketsSought: 1,
      ticketsSold: 100 } },
  Promise {
    { ticketType: 'Early Bird VIP',
      ticketTypeID: 2,
      numTicketsSought: 2,
      ticketsSold: 15 } } ]
eventInfo { _id: 5de147e1ed01a505f1ee0011,
  tickets:
   [ { ticketTypeID: 1, numberOfTickets: 5 },
     { ticketTypeID: 2, numberOfTickets: 5 },
     { ticketTypeID: 3, numberOfTickets: 10 },
     { ticketTypeID: 4, numberOfTickets: 4 } ] }
TRIGGERED
e.ticketTypeID  undefined
f.ticketTypeID  1
----------------
TRIGGERED
e.ticketTypeID  undefined
f.ticketTypeID  2
----------------
TRIGGERED
e.ticketTypeID  undefined
f.ticketTypeID  3
----------------
TRIGGERED
e.ticketTypeID  undefined
f.ticketTypeID  4
----------------
TRIGGERED
e.ticketTypeID  undefined
f.ticketTypeID  1
----------------
TRIGGERED
e.ticketTypeID  undefined
f.ticketTypeID  2
----------------
TRIGGERED
e.ticketTypeID  undefined
f.ticketTypeID  3
----------------
TRIGGERED
e.ticketTypeID  undefined
f.ticketTypeID  4
----------------

What am I doing wrong that is prevent Promise.all from using the values from the first Promise?

Upvotes: 1

Views: 775

Answers (1)

Andrei
Andrei

Reputation: 1216

I think it's because you have an array of Promises not a single Promise

let numTicketsSought = req.body.numTicketsSought.map(e => { return(

    Ticket.find({
        userEvent: req.body.userEvent,
        ticketTypeID: e.ticketTypeID
    }).lean().countDocuments()
    .then(number => {
        e.ticketsSold = number
        return e
    }))

}) 

The problem here is that Array.prototype.map will return an array.

Promise.All([]) in your case you are doing Promise.all([[],]) You will need to unwrap your promises and concatenate them all together

numTicketsSought.push(eventInfo);
Promise.all(numTicketsSought) // <-- rename numTicketsSought to something better like promisesToComplete

Upvotes: 1

Related Questions