我有一个从远程服务器或磁盘上的本地缓存获取JSON对象的函数。
在用例中,我必须使用不同的参数调用此函数几千次,但是当我这样做时,我得到最大堆栈溢出错误。我必须在某个地方进行递归调用,但我无法看到它的位置,因为我的process.nextTick函数调用似乎在正确的位置。
我在控制台中没有得到任何log.error读数,如果进行了任何重试请求的递归调用,这将是显而易见的。
控制台输出显示
重复出现(节点)警告:检测到递归process.nextTick。这将在下一版本的节点中中断。请使用setImmediate进行递归递延。
...然后
RangeError:超出最大调用堆栈大小
然后程序退出。
任何人都可以就我可能做错的事情提供任何帮助吗?我完全难过了。
下面是调用有问题函数的函数" tf2inv.loadInventory()"
function refreshInventories(accounts, force, callback) {
//job executes download function, then pushes to inventories object
var inventories = {};
var Qinv = async.queue(function (task, invCallback) {
tf2inv.loadInventory(
task.force,
task.steamid,
function(inv, alias) {
inventories[alias] = inv;
process.nextTick(invCallback);
}
);
}, 100)
//when all queue jobs have finished, callback with populated inventories object
Qinv.drain = function (err) {
log.info('All inventories downloaded');
callback(inventories);
}
//adding jobs to the queue
for (var i = accounts.length - 1; i >= 0; i--) {
Qinv.push({
force: force,
steamid: accounts[i]
});
};
}
此处显示的是从缓存中解析的函数,或来自远程服务器的请求。
//tf2inv
var loadInventory = function(force, sid, callback) {
var invLoc = invFolder+sid
if(force) {
if(fs.existsSync(invLoc)) {
fs.unlinkSync(invLoc);
}
}
if(fs.existsSync(invLoc)) {
var body = fs.readFileSync(invLoc);
try {
var inventory = JSON.parse(body);
} catch (e) {
fs.unlinkSync(invLoc);
log.error("parsing " + sid+"'s inventory");
loadInventory(true, sid, invFolder, callback);
return;
}
process.nextTick(function() { callback(inventory, sid) })
return;
} else {
var urlPre = "http://api.steampowered.com/IEconItems_440/GetPlayerItems/v0001/?key=";
var urlSidPre = "&steamid=";
var urlInvSuf = "&inventory=yes";
var URL = urlPre+steam_API+urlSidPre+sid+urlInvSuf;
http.get(URL, function (res) {
var body = '';
res.on('data', function (data) {
body+=data;
fs.appendFile(invLoc, data);
});
res.on('end', function() {
try {
inventory = JSON.parse(body);
} catch (e) {
if(fs.existsSync(invLoc)) {
fs.unlinkSync(invLoc);
}
log.error("parsing " + sid+"'s downloaded inventory");
loadInventory(force, sid, invFolder, callback)
return;
}
process.nextTick(function() { callback(inventory, sid) })
return;
});
res.on('error', function (e, socket) {
log.error(sid + " inventory error")
if(fs.existsSync(invLoc)) {
fs.unlinkSync(invLoc);
}
log.debug('Retrying inventory')
loadInventory(force, sid, invFolder, callback);
return;
})
res.on('close', function () {res.emit('end'); log.error('connection closed')})
})
.on('error', function(e) {
log.error(JSON.stringify(e));
if(fs.existsSync(invLoc)) {
fs.unlinkSync(invLoc);
}
log.debug('Retrying inventory')
loadInventory(force, sid, invFolder, callback)
return;
})
}
};
答案 0 :(得分:0)
很可能无法解析从服务器返回的正文。然后它立即再次调用自身,再次失败,无限循环并导致堆栈溢出。
我建议您不要在失败的解析时自动重试 - 如果失败一次,它可能会再次失败。最好回调一下错误,让你的编程部分调用它来处理错误,或者将它传回给可以让用户知道出错的地方。