P.K. P.K. - 8 days ago 5
Node.js Question

node.js & express, redirect or send file after async db search

I am trying to write routes for my node.js & express application and having a little problem.

The logic is this:


  1. user enter website with special tag id
    /6758HDE

  2. i do async check in db if tag already exists

  3. if tag exists i roll new unique tag and set url with it

  4. if tag doesnt exist i allow current tag and set url with it



so far this is my code:

app.get('/*', function(req, res) {
check_in_db(req.url, function(result) {
if(result) {
res.sendFile(__dirname + '/index.html');
} else {
res.redirect('/' + roll_new_id());
}
});
});


I guess that code is not working because it does async db search while headers must be sent right away, i remember that there was something like
next()
to deal with this kind of situation but my knowledge is very weak, maybe someone could point me in right track and show how to change my code so it will work as intended.

Answer

res.redirect happens before your roll_new_id function call has a chance to return the new id value. To get around this you have to call roll_new_id first, and pass in a callback function that it will call once it is done creating the new id. Once the new id value has been created it will execute the callback function passing the new id value as an argument. Inside the callback function that is passed to roll_new_id you'll do res.redirect using the new id value that was passed from roll_new_id when it executed the callback function. Does this make sense?

function roll_new_id(callbackFunction){

  var new_id;

  // create the new id...

  // pass new_id to the callback function..
  callbackFunction(new_id); 

}

app.get('/*', function(req, res) {

    check_in_db(req.url, function(result) {

        if(result) {

            res.sendFile(__dirname + '/index.html');

        } else {


            roll_new_id(function(theNewId){

              // this is the callbackFunction
              // called from inside the roll_new_id function

              res.redirect('/' + theNewId);

            })

        }
    });
});

You could also write it like this:

function rollNewIDCallbackFunction(theNewId) {

  // this is the callbackFunction
  // called from inside the roll_new_id function

  res.redirect('/' + theNewId);

}

roll_new_id(rollNewIDCallbackFunction);

If you want to use the next function do this:

app.get('/*', function(req, res, next) {

    check_in_db(req.url, function(result) {

        if(result) {

            res.sendFile(__dirname + '/index.html');

        } else {

            next(); // call middleware to roll new id

        }
    });

}, function(req, res){ // middleware to roll the new id

  function rollNewIDCallbackFunction(theNewId) {

    // this is the callbackFunction
    // called from inside the roll_new_id function

    res.redirect('/' + theNewId);

  }

  roll_new_id(rollNewIDCallbackFunction);

});