1

我对在 node.js 上工作的方式感到很困惑,我说的是回调、返回和源代码的执行方式。

我正在使用sails.js,但我认为它没有关联,我认为这更像是JS的工作方式。

源代码:

module.exports = function (req, res, callback) {
    if (req.session.authenticated) {
        // Accept user authentication.
        return callback();
    } else {
        // Not authenticated. Try auto authentication.
        if(validator.check([validator.rulesHardwareId(req.param('hardwareId'))])){
            Device.findOne({hardwareId: req.param('hardwareId')}, function(err, device){
                if(err){
                    return res.json({message: "You are not permitted to perform this action. You have to connect to the platform before. [Wrong hardwareId or DB error]", data: {err: err}, status: false}, 403);
                }

                if(device){
                    // Connect the device.
                    req.session.authenticated = true;
                    req.session.from = 'device';

                    // Search for the device's owner.
                    User.findOne({id: device.userId}, function(err, user){
                        if(err){
                            return res.json({message: "DB error.", data: {err: err}, status: false}, 403);
                        }

                        if(user){
                            // Add data about the user.
                            req.session.user = user;
                            return callback();
                        }else{
                            return res.json({message: "Device found but device's owner doesn't found.", data: {err: err}, status: false}, 403);
                        }
                    });
                }else{
                    return res.json({message: "You are not permitted to perform this action. You have to connect to the platform before. [Wrong hardwareId]", data: {err: err}, status: false}, 403);
                }
            });
        }
        return res.json({message: "You are not permitted to perform this action. You have to connect to the platform before. [Give hardwareId ?]", data: {}, status: false}, 403);

    }
};

代码不是那么重要,问题是我收到了这条消息:“您不允许执行此操作。您必须先连接到平台。[Give hardwareId ?]”

但是动作是创建的。好的,所以我调用 callback() 并返回它,但源代码继续吗?并执行最后一行?为什么?我不明白。如果我将最后一行放在 ELSE 中,我会收到消息“操作已创建”。

如果有人可以解释我.. 我认为添加 return 关键字对于防止这种情况很有用,但看起来我错了。

谢谢你。

4

2 回答 2

4

当您像代码一样发出异步请求时,执行流程不会等待响应。它只是继续下去,好像没有什么可以阻止它(因为那里什么都没有)。所以你的 main 函数会立即返回。

return您提供的嵌套语句正在向这些嵌套函数的调用者返回一个值。那么来电者是谁?好吧,您将这些函数作为参数传递给某些内部代码,因此内部代码是调用者,并且该内部代码可能不关心return值。

所以这意味着所有这些return语句都没有做任何有用的事情,因为您的主函数已经返回,并且调用您的函数的代码忽略了它们。

所以你会怎么做?好吧,正如您所看到的,您正在接收一个callback传递给您的函数的module.exports函数。因此,您应该做的是将通常return作为参数的数据传递给callback. 然后作为传递的任何函数都callback将接收该数据,并使用它做任何你想做的事情。

module.exports = function (req, res, callback) {
    if (req.session.authenticated) {
        // Accept user authentication.
        callback();
    } else {
        // Not authenticated. Try auto authentication.
        if(validator.check([validator.rulesHardwareId(req.param('hardwareId'))])){
            Device.findOne({hardwareId: req.param('hardwareId')}, function(err, device){
                if (err) {
                    callback(res.json({message: "You are not permitted to perform this action. You have to connect to the platform before. [Wrong hardwareId or DB error]", data: {err: err}, status: false}, 403));
                } else if (device) {
                    // Connect the device.
                    req.session.authenticated = true;
                    req.session.from = 'device';

                    // Search for the device's owner.
                    User.findOne({id: device.userId}, function(err, user){
                        if (err) {
                            callback(res.json({message: "DB error.", data: {err: err}, status: false}, 403));
                        } else if (user) {
                            // Add data about the user.
                            req.session.user = user;
                            callback();
                        } else {
                            callback(res.json({message: "Device found but device's owner doesn't found.", data: {err: err}, status: false}, 403));
                        }
                    });
                } else {
                    callback(res.json({message: "You are not permitted to perform this action. You have to connect to the platform before. [Wrong hardwareId]", data: {err: err}, status: false}, 403));
                }
            });
        } else {
            callback(res.json({message: "You are not permitted to perform this action. You have to connect to the platform before. [Give hardwareId ?]", data: {}, status: false}, 403));
        }
    }
};

所以你的函数会被这样调用:

 // This is the callback ------v
my_module(the_req, the_res, function(err) {
    if (err) {
        // do something with the error
        console.log(err);
    }
});
于 2013-10-09T23:07:12.737 回答
0

这可能不是您问题的直接答案。但我相信它会帮助其他相关的人。


考虑以下情况:

情况 1:没有使用 return 并且函数是异步的。

(function caller(){
    var returnedValue;
    /* Following cannot be the case
    returnedValue = callee("TestParam");
    */
    calleeWithoutReturn("TestParam", function(returnFromCallback){
        console.log(returnFromCallback);
    });
})()//() is to init the function

function calleeWithoutReturn(params, callback){
    console.log("Received Param value", params); 
    callback("Return Value Here");
    /* Here the callback is actually the function which get passed over here. 
       You can actually call/execute it as many times as you want and it does that.
       Following is the sample code
    */
    for (i = 0; i < 5; i++) { 
        callback("Return Value Here " + i);
    }
}

案例2:使用return并且函数仍然是异步的

(function caller(){
    var returnedValue;
    /* Following cannot be the case
    returnedValue = callee("TestParam");
    */
    calleeWithReturn("TestParam", function(returnFromCallback){
        console.log(returnFromCallback);
    });
})()//() is to init the function

function calleeWithReturn(params, callback){
    console.log("Received Param value", params); 

    //Try adding return here as well. It stops executing next statements and control exits.
    callback("Return Value Here"); 

    /* Here the callback is actually the function which get passed over here. 
       You can actually call/execute it as many times as you want and it does that.
       Following is the sample code
    */
    for (i = 0; i < 5; i++) { 
        return callback("Return Value Here " + i); //When return executed it exits from the for loop & this functino function.
    }
}

案例3:使用return且函数为sync的地方。

(function caller(){
    var returnedValue;
    returnedValue = calleeWithReturn("TestParam");
    console.log("caller received the return value:", returnedValue);

})()//() is to init the function

function calleeWithReturn(params){
    console.log("Received Param value", params);
    return "Params returned from callee function " + params 
}

情况 4:没有使用 return 并且函数是同步的。

(function caller(){
    var returnedValue;
    returnedValue = calleeWithReturn("TestParam");
    console.log("caller received the return value:", returnedValue); //Undefined if you dont return any value.

})()//() is to init the function

function calleeWithReturn(params){
    console.log("Received Param value", params);
    //If you dont return the function always returns 'Undefined'
    //return "Params returned from callee function " + params
}

希望现在您可以使您成为不同情况下返回的实际用例。

于 2016-11-09T05:11:07.263 回答