简体   繁体   中英

Asynchronous, promises, and closure in Mongodb

I'm new to Javascript and I'm struggling to wrap my head around asynchronous functions and promises in Javascript. I'm working with mongoose and trying to send an object of results. This is what I have so far:

Idiom.find({keywords: req.query.keyword})
    .exec(function(err, result) {

    if(err) return res.send(err);

    //loops through objects in result
    for(var i = 0; i < result.length; i++) {
        Rating.aggregate(
            [
                {
                    "$match": {
                        "idiomid": { "$eq": result[i]._id }
                    }
                },
                {
                    $group: {
                        _id: {idiomid: "$idiomid", type: "$type"},
                        rating: { $sum: "$rating"},
                        total: { $sum: 1}
                    }
                }
            ]
        ).exec(function(err, items) {
            //assign properties from items to result object
            result[i] = items;
            console.log('assigning items');
        });
        console.log('done one loop');
    }
});

The following is what I don't understand:

  1. The console prints 'done one loop' twice before printing 'assigning items'. I believe this has to do with promises and asynchronous properties.
  2. I can not access the local variable results in my Rating function. I believe this has to do with closure, but I'm not sure.

I want to be able to assign properties from items from aggregate function, then send the new result as a response. What is the best way to do this?

I redid the entire function by splitting it into several async functions. This will wait for the queries to complete before executing the next line.

idiomController.search = async(req, res, next) => {
    var results = await findIdiom(req.query.keyword);
    var temp = [];
    for(var i = 0; i < results.length; i++) {
        var agg = await aggregateResults(results[i]);
        temp.push({
            rating: agg[0].rating,
            total: agg[0].total
        });
    }
    //handle response
}

aggregateResults = (result) => {
    return Rating.aggregate(
        [
            {
                "$match": {
                    "idiomid": { "$eq": result._id }
                }
            },
            {
                $group: {
                    _id: {idiomid: "$idiomid", type: "$type"},
                    rating: { $sum: "$rating"},
                    total: { $sum: 1}
                }
            }
        ]
    );
}

findIdiom = (keyword) => {
    return Idiom.find({keywords: keyword});
}

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