使用以下代码在nodejs + mongoose + async中进行同步有什么问题?

时间:2013-05-08 00:13:55

标签: node.js asynchronous express mongoose

以下代码有什么问题?我收藏了mongo的水果,蔬菜和糖果。 “testlist”包含包含食物的字符串,这些食物属于要在集合中查找的三个类别之一。

出于某种原因,convertedList似乎从不包含“糖果”,只包含水果和蔬菜。

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);
    });

为什么没有将Candy添加到生成的“convertedList”中?我该如何解决这个问题?

注意:我注意到当我重新安排对糖果和蔬菜的功能(完成)调用时,看起来蔬菜不会被添加到最终的convertList中,但是Candy确实如此。它似乎总是被添加到convertedLIst中的第三个函数(done)被忽略。

2 个答案:

答案 0 :(得分:0)

async.parallel回调中的这一行未传递Candy查询的结果:

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

请改为尝试:

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

答案 1 :(得分:0)

@JohhnyHK是对的。除了怀疑你的查询返回的内容不是null之外,没有其他解释为什么Candy永远不会出现在你的列表中。

此测试通过(使用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();
    });

  });
});