How to resolve promise in if statement?

Viewed 25

I have an array of objects as: { id: '1582715', email: 'email@gmail.com', isUsed: false }, and I have many documents in MongoDB with same keys. Before writing new array of objects in BD, I want to check does objects of array already been written to DB.

I wrote this func that returns array of objects that hasn't been written yet:

const forWriting = testimonalsArray.filter(isWritten => {
    if (collection.countDocuments({ id: { $eq: isWritten.id } }) < 1) return isWritten
})
console.log(forWriting)

BUT collection.countDocuments({ id: { $eq: isWritten.id } } returns Promise { <pending> }. I've tried add async await:

const forWriting = testimonalsArray.filter(async isWritten => {
    if (await collection.countDocuments({ id: { $eq: isWritten.id } }) < 1) return isWritten
})
console.log(forWriting)

but still didn't receive any result. How should I resolve this promise to have an integer to compare it with 1?

3 Answers

Since the result can only become available in some future, you cannot expect that the assignment to forWriting will be the result you need, since that assignment happens now, while the result is only there in some future.

You can do it however in an asynchronously executed callback (in the future), using Promise.all:

Promise.all(testimonalsArray.map(isWritten => 
    collection.countDocuments({ id: { $eq: isWritten.id } })
)).then(counts => {
    const forWriting = counts.map((count, i) => count < 1 && testimonalsArray[i])
                             .filter(Boolean);
                             
    console.log(forWriting);
});

This assumes that testimonalsArray will not change while awaiting the counts to come back from the backend.

You should create an async function and first await for collection.countDocuments({ id: { $eq: isWritten.id } }), and then use resolved value. Like this

(async () => {
   const dbRequest = await collection.countDocuments({ id: { $eq: isWritten.id } });
   const forWriting = testimonalsArray.filter(isWritten => {
      if (dbRequest < 1) return isWritten
   })
   console.log(forWriting)
})()

You can filter all matching documents in the collection with this single query. Here is a snippet to use in an async callback, more performant at the same time since it queries DB just a single time.

const testimonialsAlreadyInTheDB = await collection.find({
   id: { $in: testimonalsArray.map(({id}) => id)}
})

const forWriting = testimonialsArray.filter(({id}) => !testimonialsAlreadyInTheDB.find(id))
Related