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

    }
};

コードはそれほど重要ではありません。問題は、次のメッセージを受け取ったことです。

しかし、アクションは CREATED です。では、callback() を呼び出して返しますが、ソース コードは続きますか? そして最後の行を実行しますか?なんで?わかりません。最後の行を ELSE にすると、「アクションが作成されました」というメッセージが表示されます。

誰かが私に説明できれば.. return キーワードを追加するとこれを防ぐのに役立つと思いましたが、間違っているようです。

ありがとうございました。

4

2 に答える 2

4

コードのように非同期リクエストを行うと、実行フローはレスポンスを待ちません。あたかもそれを妨げるものは何もないかのように、それはただ進み続けます (そこには何もないからです)。したがって、メイン関数はすぐに戻ります。

returnあなたが提供したネストされたステートメントは、それらのネストされた関数の呼び出し元に値を返しています。それで、電話の相手は誰ですか?これらの関数を引数として内部コードに渡しているので、内部コードが呼び出し元であり、その内部コードはおそらく値を気にしませんreturn

したがって、これが意味することは、これらのreturnステートメントはすべて、メイン関数が既に返されており、関数を呼び出すコードがそれらを無視しているため、まったく役に立たないということです。

それで、あなたは何をしますか?ご覧のとおり、callback関数に渡される関数を受け取っていますmodule.exportsreturnしたがって、通常は引数としてデータを渡す必要があります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 が使用され、function が 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 が使用されず、関数が sync である場合。

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

さまざまなケースで return の実際の使用例を作成できることを願っています。

于 2016-11-09T05:11:07.263 に答える