未定义的返回值mongoose / nodejs递归函数

时间:2017-01-03 20:26:21

标签: javascript node.js mongodb recursion mongoose

我希望使用递归函数来查看mongodb中是否存在使用mongoose和nodejs的用户名。

我使用回调,但我不明白为什么我的函数返回未定义的结果。你能救我吗?

谢谢;)

var mongoose = require('mongoose');
var debug = require('debug')('gc:model:User');

var UserSchema = new Schema({

  username: {type: String, required: true, trim: true, index: {unique: true, dropDups: true}},
  email: {type: String, trim: true},

  role: {type: String, required: true, default: 'user'},

});

generateUsername = function (username, number) {
  'use strict';

  var i = 0;
  var usernames = [];
  usernames.push(username);

  while (i < number) {
    var count = parseInt(usernames[i].substr(-1));
    if (count >= 0) {
      count += 1;
    } else {
      count = 0;
    }
    usernames.push(usernames[i].substring(0, count === 0 ?     usernames[i].length : usernames[i].length - 1) + count);
    i++;
  }

  return usernames;
};


findUniqueUsername = function (usernames, cb) {
  'use strict';
  if (usernames.length === 0) {
    return cb(null);
  }

  // If one of the username is undefined, go the next one
  if (typeof usernames[0] === 'undefined') {
    usernames.shift();
    findUniqueUsername(usernames);
  }

  _db.User.findOne({'username': usernames[0]}).exec(function (err, user) {
    if (err) return cb(err);

    if (user) {
      debug('Bu ! => ', usernames[0]);
      usernames.shift();
      findUniqueUsername(usernames);
    }
    else {
      debug('GooD ! => ', usernames[0]); // Value OK i have
      return usernames[0]; // Value Not OK undefined :(
    }
  });

};

var namestart = "jobs";

var usernameTries = generateUsername(namestart, 100);
var username = findUniqueUsername(usernameTries); // is undefined

2 个答案:

答案 0 :(得分:0)

变量username将保持未定义,因为您正在执行异步调用。

如果您从生成100个用户名开始,则可以查询所有用户名,然后过滤掉不存在的用户名。您仍然可以通过再次调用findUniqueUsernames并传递回调来使用此递归。

'use strict';

const mongoose = require('mongoose');

let UserSchema = new Schema({

  username: {
    type: String,
    required: true,
    trim: true,
    index: {
      unique: true,
      dropDups: true}
    },
  email: {
    type: String,
    trim: true
  },

  role: {
    type: String,
    required: true,
    default: 'user'
  },

});

var generateUsernames = function (username, number) {

  let usernames = new Array(number - 1)
  .fill(username)
  .map((username, index) => username + index);

  usernames.unshift(username);

  return usernames;
};

var findUniqueUsernames = function (usernames, callback) {
  if (usernames.length === 0) return callback(null, null);

  _db.User.find({
    username: {
      $in: usernames
    }
  })
  .select('username')
  .exec((err, results) => {
    if (err) return callback(err, null);
    else {
      let existingUsernames = results.map(r => r.username);
      let uniqueUsernames = usernames
        .filter(username => existingUsernames.indexOf(username) < 0);
      return callback(null, uniqueUsernames);
     // as an alternative, you could check here, 
     // if uniqueUsernames.length === 0
     // and use findUniqueUsernames recursive by passing the same callback again
     // return findUniqueUsernames(newSetOfPossibleUsernames, callback)
    }
  });
};

var namestart = 'jobs';

var usernameTries = generateUsernames(namestart, 100);

findUniqueUsernames(usernameTries, (err, uniqueUsernames) => {
  if (err) {
    console.log(err);
  } else {
    console.log(uniqueUsernames);
  }
});

在更多mongoosie世界中,我会使findUniqueUsernames至少成为UserSchema的静态方法:

UserSchema.statics.findUniqueUsernames = function( ...

并将_db.User.find( ...替换为

this.find( ...

答案 1 :(得分:0)

这是异步调用,用户名将是未定义的。

else {
  debug('GooD ! => ', usernames[0]); // Value OK i have
  return usernames[0]; // Value Not OK undefined :(
}

更改为

else {
  debug('GooD ! => ', usernames[0]);
  return cb(null, usernames[0]);
}

var username = findUniqueUsername(usernameTries);

更改为

var username;
findUniqueUsername(usernameTries, function(err, data){
  username = data;
});

回调是一段可执行代码,作为参数传递给其他代码,期望在某个方便的时候回调(执行)参数。调用可以像在同步回调中​​一样立即执行,也可以在稍后的时间发生,就像在异步回调中一样。 (维基百科)。 在您的情况下,在findUniqueUsername函数完成时调用它。