在模块中两次调用相同的函数失败

时间:2017-12-19 10:41:11

标签: javascript node.js node-modules

我正在建立一个node.js模块来与机器人交互,我必须根据另一个REST调用的结果获得一个REST资源(两者都是GET)。

当我这样做时,我首先调用模块中的一个函数来构造REST资源的url,然后我在" node-rest-client"中使用它。模块。

问题是我需要将这个模块用于多个机器人,这些机器人具有单独的ip地址和一些不同于机器人到机器人的其他参数(如果你愿意,我需要将它作为一个类使用)。 / p>

我的模块被称为mir100.js,如下所示

 private getUrlParameter(sParam) {
    return decodeURIComponent(window.location.search.substring(1)).split('&')
      .map((v) => v.split('='))
      .filter((v) => v[0] === sParam )
      .reduce((prev, curv, index, array) => curv[1], undefined);
  }

在我的主node.js中,我有以下内容:

var Client = require('node-rest-client').Client;
var rest = new Client(); 

/* Make the mir function act as a constructor
* use: var robot = new mir("192.168.42.111");
* or: var robot = new mir();//default ip = 192.168.12.20
*/
module.exports = mir;
function mir(ip) {
    this.g_robotPositions = [];
    this.HOST = "192.168.12.20";
    this.PORT = "8080";
    this.VERSION = "v1.0.0";
    if(arguments.length === 1){ 
        console.log("IP address is defined as argument: " + ip);
        this.HOST = ip; 
    }
}

/** Construct url
* Private function/method
* @param {string} path is the path of the url resource
* @param {boolean} predefined if true, this is indicates the path is taken from the MiR REST (includes /v1.0.0/...) default=false
* @return {string} url to the desired resource
*/
mir.prototype.ConstructURL = function(path, predefined){
    if(predefined == "undefined") predefined = false;
    if(predefined == true){
        return "http://" + this.HOST + ":" + this.PORT + path;
    }
    var url = "http://" + this.HOST + ":" + this.PORT + "/" + this.VERSION
    if(path[0] == '/') url += path;
    else url += "/" + path;
    return url;
}

/** Get all details about positions belonging to a specific map (guid) 
* @param map The map guid to get positions from
* @param callback A callback function, that returns any errors that might have occurred. The callback function takes the standard javascript argument format of (error, data)
*/
mir.prototype.GetPositionsFromMap = function(map,callback){
    g_robotPositions = [];
    var url = this.ConstructURL("maps/" + map + "/positions");

    var req = rest.get(url,function(data,response){
        if(response.statusCode >= 200 && response.statusCode < 300){

            var posCnt = data.length;
            for(var ii in data){
                console.log("data["+ii+"].url: " + data[ii].url);
                // This call to ConstructURL(...) fails and says "TypeError: this.ConstructURL is not a function"
                var tmpUrl = this.ConstructURL(data[ii].url);

                var req2 = rest.get(tmpUrl,function(data,response2){
                    if(response2.statusCode >= 200 && response2.statusCode < 300){
                        g_robotPositions.push(data);
                        if(g_robotPositions.length == posCnt){
                            callback(null,g_robotPositions);
                        }
                    }
                    else{
                        var error2 = {
                            "error":response2.statusCode,
                            "url":tmpUrl,
                            "robot":this.HOST,
                            "source":"mir100.js - GetPositionsFromMap()"
                        }
                        console.log(JSON.stringify(error2),error2.source,{"robot":this.HOST});
                        callback(error, null);
                    }
                });

                req2.on("error",function(err2){
                    console.log("Error GetPositionsFromMap 2: " + err2);
                });
            }
        }
        else{
            error = {
                "error":response.statusCode,
                "url":url,
                "robot":this.HOST,
                "source":"mir100.js - GetPositionsFromMap()"
            }
            console.log(JSON.stringify(error),error.source,{"robot":this.HOST});
            callback(error, null);
        }
    });

    req.on("error",function(err){
        console.log(err,"mir100.js - GetPositionsFromMap()",{"robot":this.HOST})
        callback(err, null);
    });
}

/** Get a list of all the maps on the robot 
* @param callback A callback function, that returns any errors that might have occurred. The callback function takes the standard javascript argument format of (error, data)
*/
mir.prototype.GetMaps = function(callback){
    var url = this.ConstructURL("maps");

    var req = rest.get(url,function(data,response){
        if(response.statusCode >= 200 && response.statusCode < 300){
            callback(null, data);
        }
        else{
            error = {
                "statusCode":response.statusCode,
                "url":url,
                "robot":this.HOST,
                "source":"mir100.js - GetMaps()"
            }
            console.log(JSON.stringify(error),error.source,{"robot":this.HOST});
            callback(JSON.stringify(error), null);
        }
    });

    req.on("error",function(err){
        console.log(err,"mir100.js - GetMaps()",{"robot":this.HOST})
        callback(err, null);
    });
}

当我运行代码时,我在控制台中出现以下错误

var mir = require('./mir100.js');

var robot = new mir();

robot.GetMaps( function(err,data){
    if(!err){
        robot.GetPositionsFromMap(data[1].guid,function(err,posData){
            if(!err){
                console.log("getPositionsFromMap: " + JSON.stringify(data));
            }
            else{
                console.log("Error getPositionsFromMap: " + err); 
            }
        });

    }
    else{
        console.log("Error GetMaps: " + err); 
    }
});

为什么我无法使用此功能两次? 我担心它与调用TypeError: this.ConstructURL is not a function at C:\Projects\Active\AL10-2.0\al10-server\js\mir100.js:498:23 at C:\Projects\Active\AL10-2.0\al10-server\node_modules\node-rest-client\lib\node-rest-client.js:539:13 at Object.parse (C:\Projects\Active\AL10-2.0\al10-server\node_modules\node-rest-client\lib\nrc-parser-manager.js:142:13) at ConnectManager.handleResponse (C:\Projects\Active\AL10-2.0\al10-server\node_modules\node-rest-client\lib\node-rest-client.js:538:32) at ConnectManager.handleEnd (C:\Projects\Active\AL10-2.0\al10-server\node_modules\node-rest-client\lib\node-rest-client.js:531:18) at IncomingMessage.<anonymous (C:\Projects\Active\AL10-2.0\al10-server\node_modules\node-rest-client\lib\node-rest-client.js:678:34) at emitNone (events.js:91:20) at IncomingMessage.emit (events.js:185:7) at endReadableNT (_stream_readable.js:974:12) at _combinedTickCallback (internal/process/next_tick.js:74:11) 的for循环有关,但我不明白为什么那会是一个问题......

1 个答案:

答案 0 :(得分:0)

问题在于Dim i As Long, lngColor as Long 'It is inadvisable to declare variables which could also be the name of built in functions and objects, in your case I would not declare "rows" as a variable as it is also a property of an object Dim varVal as Variant Dim ws As Worksheet Set ws = Thisworkbook.Worksheets("Sheet1") 'As general advice, avoid active and select but used fixed values, this way no confusion can exist as to which sheet is used In my example it is Sheet1, but you have to set it to the actual name of your sheet with ws For i = 1 To .UsedRange.Rows.Count Select Case .Cells(i, 1) 'Looks at the value of row i column A, and then below if it matches a case. Case "Unexpected Status" varVal = "Pass" lngColor = 13434828 Case "At Risk" varVal = "At Risk" lngColor = 8420607 Case "Requirements Definition" varVal = "Failed" lngColor = 10092543 Case else varVal = Empty lngColor = 0 End Select .Cells(i, 16) = varVal 'row i in column P is set to the value determined by the condition in the select case part If Not lngColor = 0 Then 'This value of lngColor is only present if the select case did not match and if so, the color should not be changed .Range(.Cells(i, 1), .Cells(i, 16)).Interior.Color = lngColor 'Set the range of row i column A to column P to the color specified by the case select. End If Next i End With 在函数内部调用时的上下文。

在为this声明回调函数时,您应该使用bind(this)

rest.get

var req = rest.get(url,(function(data,response){...}).bind(this)); 也是如此。

以下是req.on("error", ...)的完整代码:

GetPositionsFromMap