2017-01-03 33 views
0

私はmongooseとnodejsを持つ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 
+0

[非同期呼び出しからの応答を返すにはどうすればよいですか?](http://stackoverflow.com/questions/14220321/how-do-i-return-the-response-from-an-asynchronous-呼び出し) – nem035

+0

どの関数呼び出しが未定義に戻っていますか?あなたのコンソールに何かエラーがありますか? – Cruiser

+0

おそらく 'findUniqueUsername'は非同期呼び出しを含んでいますが、OPは同期メソッドで結果を読み取ろうとします。つまり、' var username = findUniqueUsername(usernameTries); 'です。ほとんどの場合、上記の提案の複製としてクローズする必要があります – nem035

答えて

0

あなたは非同期呼び出しを予備成形されているように、可変usernameは、未定義のままになります。

100人のユーザー名を生成することから始めれば、すべてのユーザー名を照会し、存在しないユーザーを除外することができます。 findUniqueUsernamesを呼び出してコールバックを渡すことで、この再帰的な呼び出しを引き続き使用できます。よりmongoosieの世界で

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

、私はUserSchemaのfindUniqueUsernamesは、少なくとも静的メソッドになるだろう:

UserSchema.statics.findUniqueUsernames = function(... 

this.find(... 
0

_db.User.find(...を置き換えるこれは非同期呼び出しとユーザー名の意志であります定義されていない。

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機能が実行されたときに呼び出されます。

関連する問題