2

After user click the login button, server closes itself by displaying an error that "Can't set headers after they are send." Any help?

Server.js file

app.put('/users/signin',function(req,res,next){
    db.collection('users',function(err,usersCollection){
        usersCollection.findOne({username:req.body.username},function(err,user){
            bcrypt.compare(req.body.password,user.password,function(err,result){
                if(result){
                    var token = jwt.encode(user,JWT_SECRET);
                    return res.json({token:token});
                }else{
                    res.status(400).send();
                }
            })
        });   
    });
    res.send();
});

Controller from where i am making call to server..

$scope.signin = function(){
                  $http.put('/users/signin',{username:$scope.username,password:$scope.password})
         .then(function(res){
               $cookies.put('token',res.data.token);
               $scope.currentUser = $scope.username;
               alert("Successfully signed in");
           },function(err){
               alert("bad login credentials");
           });
    };
ravi
  • 1,130
  • 16
  • 29

1 Answers1

1

usersCollection.findOne is async and its callback is called after res.send(); as been called.

Move the res.send(); into the bcrypt.compare callback.

app.put('/users/signin', function(req, res, next) {
    db.collection('users', function(err, usersCollection) {
        usersCollection.findOne({ username: req.body.username }, function(err, user) {
            bcrypt.compare(req.body.password, user.password, function(err, result) {
                if (result) {
                    var token = jwt.encode(user, JWT_SECRET);
                    res.json({ token: token });
                } else {
                    res.status(400);
                }

                // like here
                res.send();
            });
        });
    });
});

What's a callback?

From wikipedia, a callback is a piece of executable code that is passed as an argument to other code. There's nothing async by definition with a callback, but it's a really useful concept to use with async programming.

In JavaScript, a function can take a function reference as an argument which will serve as a callback.

function someFunction(callback) {
    console.log("before async callback");
    setTimeout(callback, 1); // calls the callback asynchronously
    console.log("after async callback");
}

It could be called like this, using an existing function

function myExistingFunction() {
    console.log("inside a callback");
}
someFunction(myExistingFunction); 

or like this, using a function expression

someFunction(function(){ 
    console.log("inside a callback");
});

Both calls to someFunction would print the following to the console in that order:

before async callback
after async callback
inside a callback

Why in that order?

Since someFunction pass the callback to the async function setTimeout, the callback is not called immediately, but only after the call stack finishes. So someFunction completely finishes, then sometime later, our callback is called.

Take a look at

Community
  • 1
  • 1
Emile Bergeron
  • 17,074
  • 5
  • 83
  • 129
  • Hi.. Thanks for reply...I removed res.send() its working but now it's giving me another error $cookies.put is not a function..... – ravi Oct 12 '16 at 20:16
  • @ravi that's another problem, so ask another question. – Emile Bergeron Oct 12 '16 at 20:16
  • @ravi best thanks on SO are upvotes and accepts, whenever you can (I know it's limited with reputation). – Emile Bergeron Oct 12 '16 at 20:40
  • actually i tried to upvote and accept answer as soon as you gave me solution, but i couldn't do it due to restrictions. Though now i have accepted solution...that i could do. By the way, can you explain me that async function and its callback... I mean i solved problem but couldn't understand what happened there – ravi Oct 12 '16 at 20:49
  • @ravi I'll try to add more details later to the answer. – Emile Bergeron Oct 12 '16 at 20:50
  • Sure.. Looking forward to it.. Thank you very much.. :) – ravi Oct 12 '16 at 20:59
  • @ravi Sorry for the delay, I've added details about callbacks and async. – Emile Bergeron Oct 19 '16 at 00:15
  • @ravi best thanks on SO are upvotes, don't hesitate to upvote answers and questions that helped you! – Emile Bergeron Oct 20 '16 at 14:25
  • I really want to do it,But it's saying me you don't have enough reputation... I can't write answers too.. so how am i supposed to increase reputation? – ravi Oct 21 '16 at 08:54
  • @ravi Totally forgot it unlocks at 15 rep. You can [ask questions and write answers](http://stackoverflow.com/help/privileges/create-posts) or suggest edits which gives 2 rep when approved. – Emile Bergeron Oct 21 '16 at 14:42