skip to Main Content

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)
}

2

Answers


  1. Chosen as BEST ANSWER

    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 ot works for me.


  2. understanding the findIndex functionality, when findIndex has some return has not null or undefined it treat as true then it return index.

    if we take your problem async function return Promise then the promise with void itself a not null or undefined so in that case, it returns the first time of promise has a value with index 0.

    for this solution:

    1. create a prototype findIndexAsync custom function to simulate the findIndex function.

    2. apply your matching with your database query function like findById with async and return true same in returning from findIndex method of pure Javascript.

    3. arr.findIndexAsync you can use await inside async function to resolve Promise return by arr.findIndexAsync

    Thanks.

    // lets assume we have this array to be iterate
    const arr = [12, 3, 5, 6, 7]
    // we create custom find Index prototype function
    
    Array.prototype.findIndexAsync = async function(callback) {
      for (let i in this) {
        // this callback simulate same as findIndex function callback
        const data = await callback(this[i], +i, this)
        // if data has true value then break the callbakc calling an return index
        if (data) {
          return +i // as index
        }
      }
      return -1
    }
    
    // we name function find Index async function
    arr.findIndexAsync(async(accu, index) => {
      // the same you are calling findById method from mongoose you can apply 
      const data = await databaseFinById(accu);
      if (data) {
        return true
      }
    }).then(x => {
      // here you can get the index value
      //  you can set await and get the value oif index
      console.log("find matched in db:with array index: ", x)
    })
    
    /**
    database terms: not need to apply it is only for demo
    */
    
    async function databaseFinById(id) {
      const db = [1, 2, 4, 6, 5, 8, 9]
      return db.find(accu => accu === id);
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search