2017-01-03 52 views
0

我想使用函數遞歸來查看用戶名是否存在於mongodb中,並且mongoose和nodejs。未定義的返回值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

哪個函數調用返回undefined?控制檯中是否有錯誤? – Cruiser

+0

可能是'findUniqueUsername',它包含一個異步調用,但OP試圖以同步的方式從它讀取一個結果,即'var username = findUniqueUsername(usernameTries);'。上述建議很可能應該被封閉 – nem035

回答

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(... 

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函數完成時調用它。