Skip to content Skip to sidebar Skip to footer

How To Use Async Parallel For Multiple Queries

I am new in javascript. I have tried to use async.parellel function. And get 'reviewArr' and return it. Please see my code. app.get('/api/wherecritique/reviews/search/:author', fu

Solution 1:

You are not setting up the functions properly. The expected argument are function() wrappers with a callback argument which gets passed to when the contained async function completes.

You also really just want async.map instead of what you are doing, because it's output is an array of the results from the looped calls. So no need to push results into an external variable:

app.get('/api/wherecritique/reviews/search/:author', function(req,res) {

  Critique.find({author: req.params.author}, function(err,cris) {

    async.map(
      cris.map( c => c.reviewID ),
      function(id, callback) {
        Review.findOne({ id: id }, callback);
      },
      function(err,results) {
        if (err) throw err; // or something with errconsole.log(results);
        res.json(results);
      }
    );

  });
});

But in all honesty you should really be using Promises here rather than import an external library

app.get('/api/wherecritique/reviews/search/:author', function(req,res) {

  Critique.find({author: req.params.author}, function(err,cris) {

    Promise.all(
      cris.map( c =>Review.findOne({ id: c.reviewID }) )
    ).then( results => {
      console.log(results);
      res.json(results);
    }).catch( e =>console.error(e) );

  });

});

Or in a more modern way with async/await:

app.get('/api/wherecritique/reviews/search/:author', async (req,res) => {

  try {       
    let cris = awaitCritique.find({author: req.params.author});

    let results = Promise.all(
      cris.map( c =>Review.findOne({ id: c.reviewID }) )
    );
    console.log(results);
    res.json(results);
  } catch(e) {
    console.error(e);
  }

});

But in actual reality, this has nothing to do with JavaScript at all, and you really should be using MongoDB features.

Either with $lookup where supported:

app.get('/api/wherecritique/reviews/search/:author', async (req,res) => {

  try {       
    let results = await Critique.aggregate([
      { $match: { author: req.params.author } },
      { $lookup: {
        from: Review.collection.name,
        localField: 'reviewID',
        foreignField: 'id'as: 'reviews'
      }},
      { $unwind: '$reviews' }
    ]);

    results = results.map( r => r.reviews );
    console.log(results);
    res.json(results);

  } catch(e) {
    console.error(e);
  }

});

Or if you don't have that, then simply passing all id values to $in:

app.get('/api/wherecritique/reviews/search/:author', async (req,res) => {

  try {       
    let cris = awaitCritique.find({ author: req.params.author });

    let results = awaitReview.find({ id: { $in: cris.map( c => c.reviewID ) } });
    console.log(results);
    res.json(results);

  } catch(e) {
    console.error(e);
  }

});

Which means either "one" or "two" actual calls to the database depending on your MongoDB version. No need to loop async calls at all.


Finally, it's really not necessary as explained by all the above, but the correct usage of async.parallel would be:

app.get('/api/wherecritique/reviews/search/:author', (req,res) => {

  Critique.find({author: req.params.author}, (err,cris) => {

    var tasks = cris.map( c =>(callback) =>Review.findOne({ id: c.reviewID }, callback);
    );

    async.parallel(
      tasks,
      (err,results) => {
        if (err) throw err; // or somethingconsole.log(results);
        res.json(results);
      }
    )
  });
});

Post a Comment for "How To Use Async Parallel For Multiple Queries"