0

I have a game grid that I'm trying to fit into an array of rows each with a number of blocks. The blocks are stored in the same collection and have row and column fields.

My current attempt is as follows.

exports.findById = function(req,res) {
    var id = req.params.id;
    console.log('Retrieving game #' + id);
    db.games.findOne( { "_id" : ObjectId(id) }, function(err, game_obj) {
        if(err || !game_obj) {
            console.log("no game");
            res.send({'error':'An error has occurred'});
        } else {
            var rows = [];
            function getRowBlocks(err,blocks) {
                if(err || !blocks) {
                    console.log("no blocks");
                    res.send({'error':'An error has occurred'});
                } else {                    
                    console.log(blocks[0].row + " has " + blocks.length + " blocks");                   
                    rows[blocks[0].row] = blocks;
                }
            }
            for(i=0;i<game_obj.farthest_row;i++) {  
                db.blocks.find( { "game_id" : ObjectId(id), "row" : i     }).sort( { "column" : 1 }).toArray(getRowBlocks);
            }
            res.send('game', { row_list : rows, game : game_obj});
        }
    });
}

But due to the scope of the mongodb find operation called for each row I cannot actually get the blocks stored in the rows variable. And because there are multiple operations run I cannot simple put the res.send... inside the toArray callback.

I could only use one query and build the array inside the callback and then pass that on, but I think this would be a lot less efficient considering that the multiple queries are happening asynchronously and that there could be a large number of rows.

I think I could do it if I could pass the rows array into the query callback, but I haven't been able to find out if that's possible.

1 Answer 1

1

That's what async.parallel is for:

// build a list of query-functions
var queries = [];
for (var i = 0; i < game_obj.farthest_row ; i++) {
  queries.push(function(i, cb) {
    db.blocks
      .find( { "game_id" : ObjectId(id), "row" : i })
      .sort( { "column" : 1 })
      .toArray(cb);
  }.bind(this, i)); // create a partial function to create a newly scoped 'i'
}

// pass the query functions to async, which will run them in parallel,
// gather all the results, and finally call the callback function with
// the results-array
async.parallel(queries, function(err, results) {
  if (err)
    // handle error

  // results now contains the query results (array-in-array)
  results.forEach(function(blocks) {
    getRowBlocks(null, blocks); // this probably requires a rewrite...
  });
});
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.