【问题标题】:Mongoose asynchronous population error. Not calling method properlyMongoose 异步填充错误。没有正确调用方法
【发布时间】:2013-08-13 09:13:43
【问题描述】:

所以我在搞乱猫鼬的种群。他们原来的example 太可怕了。它返回了错误:

TypeError: Cannot read property 'name' of undefined
at Promise.<anonymous> (/home/kevin/LearnMongoose/population/population-basic.js:104:56)
at Promise.<anonymous> (/home/kevin/node_modules/mongoose/node_modules/mpromise/lib/promise.js:162:8)
at Promise.EventEmitter.emit (events.js:94:17)
at Promise.emit (/home/kevin/node_modules/mongoose/node_modules/mpromise/lib/promise.js:79:38)
at Promise.fulfill (/home/kevin/node_modules/mongoose/node_modules/mpromise/lib/promise.js:92:20)
at Promise.resolve (/home/kevin/node_modules/mongoose/lib/promise.js:108:15)
at Promise.<anonymous> (/home/kevin/node_modules/mongoose/node_modules/mpromise/lib/promise.js:162:8)
at Promise.EventEmitter.emit (events.js:94:17)
at Promise.emit (/home/kevin/node_modules/mongoose/node_modules/mpromise/lib/promise.js:79:38)
at Promise.fulfill (/home/kevin/node_modules/mongoose/node_modules/mpromise/lib/promise.js:92:20)

我决定修改代码以使其正常工作。这就是新代码。

var mongoose = require('mongoose')
var Schema = mongoose.Schema;

console.log('Running mongoose version %s', mongoose.version);

/**
 * Console schema
 */

var consoleSchema = Schema({
    name: String
  , manufacturer: String
  , released: Date
})
var Console = mongoose.model('Console', consoleSchema);

/**
 * Game schema
 */

var gameSchema = Schema({
    name: String
  , developer: String
  , released: Date
  , consoles: [{ type: Schema.Types.ObjectId, ref: 'Console' }]
})
var Game = mongoose.model('Game', gameSchema);

/**
 * Connect to the console database on localhost with
 * the default port (27017)
 */

mongoose.connect('mongodb://localhost/bjank', function (err) {
  // if we failed to connect, abort
  if (err) throw err;

  // we connected ok
  createData();

})

/**
 * Data generation
 */

function createGame(){
  new Game({
     name: 'Legend of Zelda: Ocarina of Time'
      , developer: 'Nintendo'
      , released: new Date('November 21, 1998')
  }).save(function(err) {
      if(err) {
        console.log(err);
      } else {
        console.log('The Game has been saved');
      }

  });
}

function createConsole(){
  new Console({
     name: 'Nintendo 64'
    , manufacturer: 'Nintendo'
    , released: 'September 29, 1996'
  }).save(function(err) {
      if(err) {
        console.log(err);
      } else {
        console.log('The Console is saved');
      }

  });
}

  function pushToGame(){


    Game.findOne({name: /^Legend of Zelda/}, function (err, game){
      if(err) {return done(err);}
      console.log(game + '\n\n');
      Console.findOne({name: /^Nintendo 64/}, function  (err, consolee) {
        console.log('\n\nPulling specifed Game console\n');
        console.log(consolee);
        game.consoles.push(consolee);
        console.log('\n\nIt somehow works');
        console.log('\nThe second print of the game(should have the N64(consolee) console in the console ref array): \n\n' + game);

      })

    });
  }


  function showGame() {
    console.log('The method showGame() has started\n\n\n\n\n');
    Game.findOne({name: /^Legend of Zelda/}), function  (err, game) {
      console.log('This is not working');
      console.log(game);
  }

  }

function createData () {
  createGame();
  createConsole();
  pushToGame();
  showGame(); 

}


function done (err) {
  if (err) console.error(err);
  Console.remove(function () {
    Game.remove(function () {
      mongoose.disconnect();
    })
  })
}

在命令行中返回结果:

The method showGame() has started


{ name: 'Legend of Zelda: Ocarina of Time',
  developer: 'Nintendo',
  released: Sat Nov 21 1998 00:00:00 GMT-0500 (EST),
  _id: 5208628ddbc8cf1302000001,
  __v: 0,
  consoles: [] }


The Game has been saved
The Console is saved


Pulling specifed Game console

{ name: 'Nintendo 64',
  manufacturer: 'Nintendo',
  released: Sun Sep 29 1996 00:00:00 GMT-0400 (EDT),
  _id: 5208628ddbc8cf1302000002,
  __v: 0 }


It somehow works

The second print of the game(should have the N64(consolee) console in the console ref array): 

{ name: 'Legend of Zelda: Ocarina of Time',
  developer: 'Nintendo',
  released: Sat Nov 21 1998 00:00:00 GMT-0500 (EST),
  _id: 5208628ddbc8cf1302000001,
  __v: 0,
  consoles: [ 5208628ddbc8cf1302000002 ] }

当我进行一些修改时它并没有中断,但正如你所见,我放置了很多控制台日志来查看整个脚本中发生了什么。行:

方法 showGame() 已启动

应该在结尾而不是开头,因为这是我调用函数的顺序。

我不知道为什么这不起作用,因为它应该,但它不是。为什么我的 showGame() 函数在我创建数据之前就被调用了,即使它是在调用创建数据之后调用的?

其他信息

我对 Node.js 的结构有点了解。我知道它是异步工​​作的。也许 showGame 函数首先运行,因为前几个函数太慢了。如果是这种情况,我怎样才能让 showGame() 函数在这种结构中排在最后?

【问题讨论】:

    标签: javascript node.js asynchronous mongoose


    【解决方案1】:

    如果没有错误,您应该在前一个方法的回调之后调用每个函数,而不是使用createData() 方法。例如:

    function createGame(){
      new Game({
         name: 'Legend of Zelda: Ocarina of Time'
          , developer: 'Nintendo'
          , released: new Date('November 21, 1998')
      }).save(function(err) {
          if(err) {
            console.log(err);
          }
          else {
            console.log('The Game has been saved');
            createConsole()
          }
      });
    }
    

    还有更冗长丑陋的解决方案:

    function createData () {
      createGame(function(error) {
        if(error) {
            throw error;
        }
        else {
            createConsole(function(err) {
                if(err) {
                    throw err;
                }
                else {
                    pushToGame(function(er) {
                        if(er) {
                            throw er;
                        }
                        else {
                            showGame(function(e) {
                                if(e) {
                                    throw e;
                                }
                                else {
                                    // rest of your code
                                }
                            });
                        }
                    });
                }
            });
        }
      });
    }
    

    【讨论】:

    • 这样我的东西就可以同步工作了,但是由于某种原因,showGame 中的第二个 findOne 函数没有。我几乎复制并粘贴了 pushToGame() 中的函数,它确实有效,因此我不知道为什么它没有成功。
    • 所以我修好了。我将该功能嵌入错误的位置。现在可以了!谢谢
    猜你喜欢
    • 1970-01-01
    • 2016-07-11
    • 2017-02-12
    • 2016-02-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-10
    相关资源
    最近更新 更多