Search code examples
javascriptarraystypescriptmongodbmongoose

findIndex() with async callback with mongoose.findById() inside always returning 0


I am creating simple queing system with tickets. The ticket is inserted into array in place of first ticket with visitTime greater than one to be inserted. The array contains only ticketIds, which have to be looked up in Mongo database using mongoose findById(ticketId) method before any comparing.

However after writing below code I noticed, that findIndex() method returns always index 0, whatever the data in the array is. What am I missing?

Here is the code:


const ticketToInsertTime = convertTime(ticket.visitTime)

const index = que.activeTickets.findIndex(async (ticketId) => {
    const ticketFromArray = await Ticket.findById(ticketId).exec()
    const ticketTime = convertTime(ticketFromArray?.visitTime!)
    return ticketTime > ticketToInsertTime
})
if (index < 0) {
    que.activeTickets.push(ticket._id)
    que.save()
} else {
    que.activeTickets.splice(index, 0, ticket._id)
    que.save()
}




function convertTime(time: string) {
    const hour = parseInt(time.split(':')[0])
    const minutes = parseInt(time.split(':')[1])

    return (hour * 60 + minutes)
}


Solution

  • I solved my problem with slightly different approach. I first fetch list of all active Tickets, then map over them one by one using for ... of loop to retrieve only data I want and finally I find index of specific object in mapped array, which reflects previous array. Code below if someone needs the solution.

    const mapTickets = async () => {
        const timeArray = []
        for (const ticket of que.activeTickets) {
            let singleTicket = await Ticket.findById(ticket).exec()
            timeArray.push(singleTicket?.visitTime)
        }
        return timeArray;
     }
     const mappedTickets = await mapTickets()
    
     const index = mappedTickets.findIndex((time) =>
         convertTime(time!) > ticketToInsertTime
     )
     if (index < 0) {
         que.activeTickets.push(ticket._id)
         que.save()
     } else {
         que.activeTickets.splice(index, 0, ticket._id)
         que.save()
     }
    

    Instead of for loop, which executes in a series, for parralell approach you could use Promise.all() for mapping.

    Maybe not the cleanest way, but it works for me.