使用sockets.io超出了node.js调用堆栈

问题描述 投票:0回答:1

我正在做一个项目,我必须继续轮询网络(本地网络)上的许多设备的状态,然后在socket.io连接上向客户端发送此状态。

当设备连接良好时,我可以启动并运行代码,但是如果其中一个从网络中掉落,我得到:

RangeError: Maximum call stack size exceeded 
    at Function.isBuffer (buffer.js:398:36)
    at hasBinary (c:\Projects\Active\AL10-2.0\al10-server_sqlite\node_modules\has-binary2\index.js:42:87)
    at hasBinary (c:\Projects\Active\AL10-2.0\al10-server_sqlite\node_modules\has-binary2\index.js:56:59)
    at hasBinary (c:\Projects\Active\AL10-2.0\al10-server_sqlite\node_modules\has-binary2\index.js:56:59)
    at hasBinary (c:\Projects\Active\AL10-2.0\al10-server_sqlite\node_modules\has-binary2\index.js:56:59)
    at hasBinary (c:\Projects\Active\AL10-2.0\al10-server_sqlite\node_modules\has-binary2\index.js:56:59)
    at hasBinary (c:\Projects\Active\AL10-2.0\al10-server_sqlite\node_modules\has-binary2\index.js:56:59)
    at hasBinary (c:\Projects\Active\AL10-2.0\al10-server_sqlite\node_modules\has-binary2\index.js:56:59)
    at hasBinary (c:\Projects\Active\AL10-2.0\al10-server_sqlite\node_modules\has-binary2\index.js:56:59)
    at hasBinary (c:\Projects\Active\AL10-2.0\al10-server_sqlite\node_modules\has-binary2\index.js:56:59)

我的代码看起来像这样:

var express = require("express");
var app = express();
var http = require("http").Server(app);
var Client = require("node-rest-client").Client;
var rest = new Client();
var io = require("socket.io")(http);
var sqlite3 = require("sqlite3");

function test(counter=0, list=[]){
    // console.log(counter);
    if(list.length == 0 || counter >= list.length){
        var query = "SELECT url FROM paths";
        db.all(query, (err,data) => {
            if(err){
                throw (err);
            }
            test(0, data);
        });
    }
    else{
        setTimeout( () => {
            GetStatus(list[counter].url, (err, restData) => {
                if(err){
                    /* As soon as one of these are added, 
                    the callstack is exceeded */
                    // setTimeout(io.sockets.emit("error", err),50);
                    // io.sockets.emit("error", err);
                    console.log(err);
                }
                else{
                    /* This one is no problem */
                    io.sockets.emit("status", restData);
                    console.log(counter + " - " + restData.HeartBeat);
                }
                // process.nextTick(test, ++counter, list);
                test(++counter, list);
            });
        },1000);
    }
}

function GetStatus(url, callback){
    var req = rest.get(url, ((data,response) => {
        if(response.statusCode == 200){
            callback(null,data);
        }
        else{
            callback(response.statusCode,null);
        }
    }).bind(this));

    req.on("error",(function(err){
        /* All of the following yeilds the same result */
        callback(err,null);
        // process.nextTick(callback,err,null);
        // setTimeout(callback(err,null),0);
    }).bind(this));
}


var db = new sqlite3.Database(":memory:", (err) => {
    if(err) return;
});

db.serialize(() => {
    var values = ["http://192.168.42.69/restapi/status","http://192.168.42.70/restapi/status"];
    db.run("CREATE TABLE paths(url text)")
    .run("INSERT INTO paths(url) VALUES (?),(?)", values, (err) => {
        if(err){
            throw err;
        }
        test();
    });
});

当我添加io.sockets.emit("error",err);(有或没有setTimeout(...))代码失败并给我RangeError。

上面的代码是一个孤立的测试,试图弄清楚它为什么不起作用。在实际应用中,还有一些网址,它们可能会随着时间的推移而改变。在实际应用程序中,此例程还将不时地在数据库中查询URL中的更改...

我试图在this post中实现一些答案,但无济于事。

所以我的问题是,为什么socket.io调用会给我的堆栈溢出?而且,我如何让它工作?

我在用

node.js - 8.9.4
socket.io - 2.0.3
sqlite3 - 3.1.13
node-rest-client - 3.1.0
express - 4.15.3
node.js socket.io callstack
1个回答
0
投票

我刚想通了。

This帖子有同样的错误,修复也在这里工作。

问题是来自err的其余调用的GetStatus(list[counter].url, (err, restData) => {...})对象。当发送它时,err对象是自引用的并且导致调用堆栈被泛洪。

将其更改为非自引用对象使其即使没有setTimeout()也能正常工作

© www.soinside.com 2019 - 2024. All rights reserved.