0

Please advise if the following code is the best way to remove an object from an array while performing async functions:

// arr1 holds objects that I've already pulled from the remote db in the past
const arr1 = [ { "hi": "there", "bye": "now" }, ... ]

const conn = connectToRemoteDB()

// loop through list of type of things that I want to pull from remote db
for (const x in listOfObjects)
{
  // this is async
  conn.execute(sql)
    .then (result => 
    {
      let exists = false
      // loop on arr1. can be thousands of objects
      for (const i in arr1)
        if (result.id === arr1[i].id)
        {
          exists = true
          arr1.splice(i, 1)
          break
        }
    }
}

// will this always be accurate so
// I know anything left in arr1 has been removed from the remote DB
pnkflydgr
  • 665
  • 3
  • 13
  • 22
  • 1
    [Don’t mutate your array while iterating](https://stackoverflow.com/q/9882284/4642212). Use [`filter`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter) instead. [Don’t use `for`–`in` on arrays](https://stackoverflow.com/q/500504/4642212). – Sebastian Simon Mar 22 '21 at 02:23
  • I'm not seeing how to use filter. Are you suggesting that I create a new array with items that do exist? Then when all async functions complete, compare the two arrays. – pnkflydgr Mar 22 '21 at 12:08
  • _“only objects that were found”_ — Have you tried _negating_ your predicate? _“about mutating an array while you're iterating on the same array. I'm not doing that”_ — Yes, you are doing that. It’s bad practice. _“Please read a question before you answer.”_ — I never answered here. – Sebastian Simon Mar 24 '21 at 00:48
  • @SebastianSimon, sorry. i'm a bit burnt out. i forgot to add a break in my original post so yes. i'm mutating the array i'm looping on but i'm then breaking out of that loop. Can you give me an example of using filter and negating the predicate? Thanks for trying to help but I'm still lost. – pnkflydgr Mar 24 '21 at 00:54

1 Answers1

0

I couldn't find a great way to do this so I went with a more synchronous approach using Promise.allSettled.

// oldObjects holds objects that I've already pulled from the remote db in the past
const oldObjects = [{ "hi": "there", "bye": "now" }]
const newObjects = []

const conn = connectToRemoteDB()

let dataPromises = []

// loop through list of type of things that I want to pull from remote db
for (const x in listOfObjects)
{
    // this is async
    dataPromises.push(conn.execute(sql))

}

Promise.allSettled(dataPromises)
    .then(results => 
    {
        results.forEach(({ status, value }) => 
        {
            if (status === "fulfilled")
            {
                for (const r in rows)
                {
                    const queryRow = rows[r]
                    // loop on oldObjects. can be thousands of objects
                    for (const i in oldObjects)
                        if (queryRow.id === oldObjects[i].id)
                        {
                            newObjects.push(queryRow.id)
                            break
                        }
                }
            }
        })

        // compare oldObjects and newObjects to find which objects are no longer in the DB
    })

I used Promise.allSettled because the dataPromises results in Arrays of Arrays of Objects.

pnkflydgr
  • 665
  • 3
  • 13
  • 22