简体   繁体   中英

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', function(req,res){
   var reviewArr = [];
   Critique.find({author:req.params.autho}, function(err,cris){
       var i =0;
       var f = function(reviewID)
      {
          Review.findOne({id:reviewID}, function(err, review)
          {
               reviewArr.push(review);
          }
      }
      var tasks = {};
      for(var j =0; j<cris.length; j++)
      {
          tasks['func'+j] = f(cris[j].reviewID);
      }
      async.parallel(tasks, function(err, results){
          console.log(results);
          res.json(reviewArr);
      });
  });
});

I used mongoose+express+node.js. Critique, Review are models(mongoose schema).

When I run this code, I get this message. "task is not a function"

Please help how can i fix this error? Regards.

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 err
        console.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 = await Critique.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 = await Critique.find({ author: req.params.author });

    let results = await Review.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 something
        console.log(results);
        res.json(results);
      }
    )
  });
});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM