Javascript Node.js出现多个get请求的意外堆栈溢出

Javascript Node.js出现多个get请求的意外堆栈溢出,javascript,node.js,stack-overflow,Javascript,Node.js,Stack Overflow,我有一个函数,可以从远程服务器或磁盘上的本地缓存获取JSON对象 在一个用例中,我必须使用不同的参数调用这个函数几千次,但是当我这样做时,我会得到最大堆栈溢出错误。我必须在某个地方进行递归调用,但我看不出它可能在哪里,因为我的进程。nextTick函数调用似乎位于正确的位置 我在控制台中没有得到log.error的读数,如果进行了重试请求的递归调用,这一点就很明显了 控制台输出显示重复出现的 (节点)警告:检测到Recursive process.nextTick。这将在节点的下一个版本中中断。

我有一个函数,可以从远程服务器或磁盘上的本地缓存获取JSON对象

在一个用例中,我必须使用不同的参数调用这个函数几千次,但是当我这样做时,我会得到最大堆栈溢出错误。我必须在某个地方进行递归调用,但我看不出它可能在哪里,因为我的进程。nextTick函数调用似乎位于正确的位置

我在控制台中没有得到log.error的读数,如果进行了重试请求的递归调用,这一点就很明显了

控制台输出显示重复出现的

(节点)警告:检测到Recursive process.nextTick。这将在节点的下一个版本中中断。请使用setImmediate进行递归延迟

然后

RangeError:超出了最大调用堆栈大小

然后程序退出

关于我可能做错了什么,有人能提供帮助吗?我完全被难住了

下面是调用有问题的函数“tf2inv.loadInventory()”的函数

这里显示的是从缓存解析或从远程服务器请求的函数

//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;
        })
    }
};

它可能无法解析从服务器返回的主体。然后它立即再次调用自己,再次失败,无限循环并导致堆栈溢出


我建议您不要对失败的解析自动重试—如果它失败一次,很可能再次失败。最好带着错误回调,让调用该错误的编程部分处理错误,或者将错误传递回可以让用户知道有问题的地方。

在该catch处理程序中,
loadInventory(true、sid、invFolder、callback)看起来可能是无限递归的。错误的堆栈跟踪是什么?Bergi,谢谢你的帮助。递归调用不会成为问题,因为该调用之前的log.error控制台输出永远不会出现。因此,堆栈跟踪不会显示,因为它是堆栈溢出错误。我的文章中详细介绍了我程序这一部分的控制台输出。Austinen您必须使用调试器并在错误时停止,这样您可以检测当前堆栈。根据记录器的不同,它可能会异步输出错误,这意味着如果进程在输出之前崩溃,您将看不到它。记录器只是console.log的代理,它具有彩色编码的日志子类型。在这种情况下。它是同步的,我会看到控制台记录错误。我看不到这一点,这让我认为问题不在于递归函数调用。当我在家时,我将删除错误处理并确认情况属实。
//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;
        })
    }
};