node.js 超出调用堆栈 sockets.io
node.js call stack exceeded with sockets.io
我正在做一个项目,我必须不断轮询网络(本地网络)上许多设备的状态,然后通过 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
我刚刚弄明白了。
This post 有同样的错误,这里的修复也有效。
问题是 GetStatus(list[counter].url, (err, restData) => {...})
中剩余调用的 err
对象。按原样发送时,err
对象是 self-referencing 并导致调用堆栈被淹没。
将其更改为 non-self 引用对象使其即使没有 setTimeout()
也能正常工作
我正在做一个项目,我必须不断轮询网络(本地网络)上许多设备的状态,然后通过 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
我刚刚弄明白了。
This post 有同样的错误,这里的修复也有效。
问题是 GetStatus(list[counter].url, (err, restData) => {...})
中剩余调用的 err
对象。按原样发送时,err
对象是 self-referencing 并导致调用堆栈被淹没。
将其更改为 non-self 引用对象使其即使没有 setTimeout()