Richard
Richard

Reputation: 32899

JavaScript control flow in node/redis: returning from inside callback?

Newbie question. Why is this JavaScript function returning undefined?

var redis = require("redis"), client = redis.createClient();
function generatePageUrl() { 
    var randomStr = randomInt.toString(32);
    // Check whether this URL is already in our database;
    client.smembers("url:" + randomStr, function (err, data ) {
        if (data.length != 0) {
            // URL already in use, try again
            return getPageUrl();
        }
        return randomStr;
    });
}
var page_url = generatePageUrl();
// add it to the database, etc

I guess it must be getting to the end and returning before it reaches the inside of client.smembers.

But I really need to check the contents of the Redis set before it returns: can I get it to return from inside the callback? If not, what can I do?

Also, advice on the way I've used this function recursively would be welcome - I'm not sure it's completely sensible :)

Thanks for helping out a newcomer.

Upvotes: 4

Views: 1539

Answers (1)

thejh
thejh

Reputation: 45568

You can't return from inside a callback. Do it like this:

var redis = require("redis"), client = redis.createClient();
function generatePageUrl(cb) { 
    var randomStr = randomInt.toString(32);
    // Check whether this URL is already in our database;
    client.smembers("url:" + randomStr, function (err, data ) {
        if (data.length != 0) {
            // URL already in use, try again
            getPageUrl(cb);
        }
        cb(randomStr);
    });
}
generatePageUrl(function(page_url){
    // add it to the database, etc
});

If you don't like this style, you might want to consider streamlinejs - it makes you able to write your code like this:

var redis = require("redis"), client = redis.createClient();
function generatePageUrl(_) { 
    var randomStr = randomInt.toString(32);
    // Check whether this URL is already in our database;
    var data = client.smembers("url:" + randomStr, _);
    if (data.length != 0) {
        // URL already in use, try again
        return getPageUrl(_);
    }
    return randomStr;
}
var page_url = generatePageUrl(_);
// add it to the database, etc

Upvotes: 2

Related Questions