【发布时间】:2018-08-05 19:03:07
【问题描述】:
我正在做一个项目,我必须不断轮询网络(本地网络)上许多设备的状态,然后通过 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,它们可能会随着时间而改变。在实际应用中,该例程还会时不时地查询数据库中 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
【问题讨论】:
-
是不是因为递归使用了test函数?
-
我怀疑是这样,但如果它在错误处理中没有调用 io.sockets.emit() 函数的情况下运行,那么它运行几个小时都没有问题。只要我在
if(err)中添加该调用,它就会崩溃...... -
这取决于你压入堆栈的程度,不是吗?您可以发布一些内容以便重现您的问题吗?还是你的代码就够了?
-
不得不改变 "setTimeout(()=>{io.sockets.emit("error", err)},50);"让它运行。
-
这在我的机器上似乎没有奏效。超出调用堆栈大小时出现相同的错误。它可能是 socket.io 模块中的东西吗?我没有附加任何客户端来接收 socket.io 消息,但我会以某种方式期望在任何其他情况下也会发生此错误......
标签: node.js socket.io callstack