【问题标题】:Node Error : can't set headers after they are sent. How to solve?节点错误:发送后无法设置标头。怎么解决?
【发布时间】:2017-02-21 18:43:37
【问题描述】:

用户单击登录按钮后,服务器会通过显示“发送后无法设置标头”错误自行关闭。有什么帮助吗?

Server.js 文件

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

我从中调用服务器的控制器..

$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");
           });
    };

【问题讨论】:

    标签: node.js express node-modules


    【解决方案1】:

    usersCollection.findOne 是异步的,它的回调在res.send(); 被调用之后调用。

    res.send(); 移动到bcrypt.compare 回调中。

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

    什么是回调?

    来自wikipedia回调是一段可执行代码,作为参数传递给其他代码。根据定义,回调没有任何异步,但它是用于异步编程的一个非常有用的概念。

    在 JavaScript 中,函数可以将函数引用作为参数,该参数将用作回调。

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

    可以这样调用,使用现有函数

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

    或者像这样,使用函数表达式

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

    someFunction 的两次调用都会按此顺序将以下内容打印到控制台:

    before async callback
    after async callback
    inside a callback
    

    为什么要按这个顺序?

    由于someFunction 将回调传递给异步函数setTimeout,因此不会立即调用回调,而是仅在调用堆栈完成后调用。所以someFunction 完全完成,然后一段时间后,我们的回调被调用。

    看看

    【讨论】:

    • 嗨.. 感谢您的回复...我删除了 res.send() 它的工作但现在它给了我另一个错误 $cookies.put is not a function.....
    • @ravi 这是另一个问题,所以再问一个问题。
    • @ravi 在 SO 上的最佳感谢是支持和接受,只要你可以(我知道它受到声誉的限制)。
    • 实际上,一旦您给了我解决方案,我就尝试投票并接受答案,但由于限制,我无法做到。虽然现在我已经接受了解决方案......我可以做到。顺便说一句,你能解释一下异步函数及其回调...我的意思是我解决了问题,但不明白那里发生了什么
    • @ravi 我稍后会尝试在答案中添加更多详细信息。
    猜你喜欢
    • 2016-07-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-05
    • 1970-01-01
    相关资源
    最近更新 更多