What is the issue with with synchronization in nodejs+mongoose+async with the following code?

What is the issue with the following code? I have collections of Fruits, Vegetables, and Candy in mongo. "testlist" contains strings containing food that fall under one of the three categories to be looked up in the collections.

For some reason, the convertedList never appears to be consisting of "candy", but only Fruits and Vegetables.

var async = require("async"),
    testlist = ["Tomato", "Carrot", "Orange", "Chocolate"];

async.map(testlist, function (food, next) {
  async.parallel([function (done) {
    Fruit.findOne({"name": food}, done);
  },
  function (done) {
    Vegetables.findOne({"name": food}, done);
  },
  function (done) {
    // The line below appears to execute successfully but never end up in "convertedList"
    Candy.findOne({"name": food}, done);
  }
], function (err, foods) { 
         next(err, foods[0] || foods[1]);
      });
    },
    function (err, result) {

      var convertedList = [].concat(result);
      res.send(convertedList);
    });

Why is Candy not being added to the resulting "convertedList"? How do I fix the issue?

Note: I've noticed when I rearrange the function(done) call for Candy and Vegetables, it appears that Vegetables dont get added to the final convertedList, but Candy does. It appears to always be the third function(done) being ignored for adding into convertedLIst.

This line in your async.parallel callback isn't passing along the result from the Candy query:

next(err, foods[0] || foods[1]);

Try this instead:

next(err, foods[0] || foods[1] || foods[2]);

@JohhnyHK is right. Other than suspecting that your queries are returning something other than null, there is no other explanation as to why Candy never appears in your list.

This test passes (using mocha):

var async = require('async'),
  should = require('should'),
  sinon = require('sinon');


describe('async map', function () {
  var Fruit, Vegetables, Candy, service;
  var noop = function () {};

  beforeEach(function () {
    Fruit = sinon.stub({ findOne: noop });
    Vegetables = sinon.stub({ findOne: noop });
    Candy = sinon.stub({ findOne: noop });

  });


  it('should map', function (done) {

    var testlist = ["Tomato", "Carrot", "Orange", "Chocolate"];

    // return null record for everything
    Fruit.findOne.yields(null);
    Vegetables.findOne.yields(null);
    Candy.findOne.yields(null);

    // return some value when query matches (simulating mongo queries basically)
    Fruit.findOne.withArgs({name: 'Orange'}).yields(null, 'Orange');
    Vegetables.findOne.withArgs({name: 'Tomato'}).yields(null, 'Tomato');
    Vegetables.findOne.withArgs({name: 'Carrot'}).yields(null, 'Carrot');
    Candy.findOne.withArgs({name: 'Chocolate'}).yields(null, 'Chocolate');

    async.map(testlist, function (food, next) {
      async.parallel([function (done) {
        Fruit.findOne({
          "name": food
        }, done);
      },
          function (done) {
        Vegetables.findOne({
          "name": food
        }, done);
      },
          function (done) {
        // The line below appears to execute successfully but never end up in "convertedList"
        Candy.findOne({
          "name": food
        }, done);
      }
      ], function (err, foods) {
        next(err, foods[0] || foods[1] || foods[2]);
      });
    }, function (err, result) {

      var convertedList = [].concat(result);
      convertedList.should.eql(testlist);
      done();
    });

  });
});