Javascript 使用Mongoose避免超过Node.JS中的调用堆栈大小

Javascript 使用Mongoose避免超过Node.JS中的调用堆栈大小,javascript,node.js,mongodb,callstack,Javascript,Node.js,Mongodb,Callstack,我对Node比较陌生,所以请指出您看到的所有错误 我试图编写一个相对简单的应用程序;取~1k个对象的JSON字符串,将它们分成若干组,并计算该组每个对象中的特定值的总和。问题是,我需要将总数精确到相当多的小数,因此,我使用的是BigDecimal(我相信这就是导致大量调用的原因) 我得到以下错误: RangeError: Maximum call stack size exceeded 我知道这个错误来自一个函数调用一个函数,如此类推,直到链变得足够长,可能成为一个无限循环。然而,这似乎也是由

我对Node比较陌生,所以请指出您看到的所有错误

我试图编写一个相对简单的应用程序;取~1k个对象的JSON字符串,将它们分成若干组,并计算该组每个对象中的特定值的总和。问题是,我需要将总数精确到相当多的小数,因此,我使用的是BigDecimal(我相信这就是导致大量调用的原因)

我得到以下错误:

RangeError: Maximum call stack size exceeded
我知道这个错误来自一个函数调用一个函数,如此类推,直到链变得足够长,可能成为一个无限循环。然而,这似乎也是由我下面的函数触发的

老实说,我被踩了一脚,不太清楚该如何解决这个问题。对于基于回调的应用程序(如Node),您可能会认为对于如何处理调用堆栈大小,已经有了完善的标准。不幸的是,我的搜索没有找到任何东西。任何帮助都将不胜感激

代码如下:

// Mongoose
mongoose.connect("mongodb://localhost/test");
var db = mongoose.connection;
db.on("error", console.error.bind(console, "connection error:"));

// If connection success
db.once("open", function() {
    // Define current period schema/model
    var Mixed = mongoose.Schema.Types.Mixed;
    var curSchema = mongoose.Schema({
        total: Mixed,
        startTime: { type: Number, default: 0 },
        lastTime: { type: Number, default: 0 },
        high: Mixed,
        low: Mixed 
    });
    var curModel = mongoose.model("curModel", curSchema);
    // Create current period
    currentPeriod = new curModel({total: new bigdecimal.BigDecimal("0"),
                                        high: new bigdecimal.BigDecimal("0"),
                                        low: new bigdecimal.BigDecimal("999") });

    curModel.find(function(err,current) {
            if (err) console.error("=== FAILED TO FIND CURRENT PERIOD! ===");
            console.log(current);
        });

    scraper.retrieve("[url-of-json]",{},
    updateOrders);
});

/* *
 * Update database with newest orders
 */
var updateOrders = function(error, r, body) {
    var response = JSON.parse(body);

    // Stop if retrieval failed
    if (error || !response || response.error) {
        console.log("Failed to retreive trade history:");
        console.log(error || response.error);
        return;
    }
    // Loop through every order, from bottom
    var k = Object.keys(response);
    for (var i = k.length - 1; i>=0; i--) {
        var j = k[i];
        var amount = new bigdecimal.BigDecimal(response[j].amount);
        var price = new bigdecimal.BigDecimal(response[j].price);

        // If we haven't logged this order yet (and it's in the current period)
        if (response[j].date >= currentPeriod.lastTime && response[j].date - currentPeriod.startTime < 900) {

            if (!(i%20)) console.log("Adding " + amount.toString() + " to total. Time: " + (response[j].date - currentPeriod.startTime) + ". I: " + i);
            currentPeriod.total = currentPeriod.total.add(amount);
            currentPeriod.lastTime = response[j].date;
            if (price.compareTo(currentPeriod.high)===1) currentPeriod.high = price;
            if (price.compareTo(currentPeriod.low)===-1) currentPeriod.low = price;
        }

        // If we've passed the 15-minute mark
        if (response[j].date - currentPeriod.startTime >= 900) {
            // If we should save
            if (currentPeriod.startTime !== 0) {
                console.log("=== Period end ("+response[j].date+") === ");
                console.log("End index: " + i);
                console.log("Total: " + currentPeriod.total.toString());
                console.log("High: " + currentPeriod.high.toString());
                console.log("Low: " + currentPeriod.low.toString());
                console.log("Closing: " + price);

                // Mark as modified
                currentPeriod.markModified("total");currentPeriod.markModified("lastTime");
                currentPeriod.markModified("startTime");currentPeriod.markModified("high");
                currentPeriod.markModified("low");
                // Save
                currentPeriod.save(function(err,period) {
                        if (err) console.error("=== Failed to save current period! ===");
                    });
            }

            currentPeriod.total = new bigdecimal.BigDecimal("0").add(amount);
            currentPeriod.lastTime = response[j].date;
            currentPeriod.startTime = response[j].date;
            currentPeriod.high = price;
            currentPeriod.low = price;
        }
    }
}
//猫鼬
猫鼬。连接(“mongodb://localhost/test");
var db=猫鼬连接;
db.on(“error”,console.error.bind(console,connectionerror:);
//如果连接成功
db.once(“打开”,函数(){
//定义当前期间架构/模型
var Mixed=mongoose.Schema.Types.Mixed;
var curSchema=mongoose.Schema({
总数:混合,
开始时间:{type:Number,默认值:0},
上次:{type:Number,默认值:0},
高:混合,,
低:混合
});
var curModel=mongoose.model(“curModel”,curSchema);
//创建当前期间
currentPeriod=new curModel({total:new bigdecimal.bigdecimal(“0”),
高:新的bigdecimal.bigdecimal(“0”),
低:新的bigdecimal.bigdecimal(“999”)});
curModel.find(函数(err,current){
if(err)console.error(“==找不到当前期间!==”;
console.log(当前);
});
retrieve(“[url of json]”,{},
更新订单);
});
/* *
*用最新订单更新数据库
*/
var updateOrders=函数(错误,r,正文){
var response=JSON.parse(body);
//如果检索失败,请停止
如果(错误| |!响应| |响应.错误){
console.log(“检索交易历史记录失败:”;
console.log(错误| |响应.error);
返回;
}
//从底部循环浏览每个订单
var k=Object.keys(响应);
对于(变量i=k.length-1;i>=0;i--){
var j=k[i];
var金额=新的bigdecimal.bigdecimal(响应[j].amount);
var price=new bigdecimal.bigdecimal(响应[j].price);
//如果我们尚未记录此订单(且该订单处于当前期间)
如果(响应[j].date>=currentPeriod.lastTime&&response[j].date-currentPeriod.startTime<900){
if(!(i%20))console.log(“将“+amount.toString()+”添加到total.Time:”+(响应[j].date-currentPeriod.startTime)+“.i:+i);
currentPeriod.total=currentPeriod.total.add(金额);
currentPeriod.lastTime=响应[j]。日期;
如果(price.compareTo(currentPeriod.high)==1)currentPeriod.high=价格;
如果(price.compareTo(currentPeriod.low)=-1)currentPeriod.low=价格;
}
//如果我们超过了15分钟
如果(响应[j].日期-currentPeriod.startTime>=900){
//如果我们应该节约
如果(currentPeriod.startTime!==0){
console.log(“==期间结束(“+响应[j].日期+”==”);
console.log(“结束索引:+i”);
log(“总计:+currentPeriod.Total.toString());
log(“高:+currentPeriod.High.toString());
log(“Low:+currentPeriod.Low.toString());
控制台日志(“收盘:+价格);
//标记为已修改
currentPeriod.markModified(“总计”);currentPeriod.markModified(“上次”);
currentPeriod.markModified(“开始时间”);currentPeriod.markModified(“高”);
本期调整后的市价(“低”);
//拯救
currentPeriod.save(函数(err,period){
if(err)console.error(“==保存当前期间失败!==”;
});
}
currentPeriod.total=新的bigdecimal.bigdecimal(“0”)。添加(金额);
currentPeriod.lastTime=响应[j]。日期;
currentPeriod.startTime=响应[j]。日期;
currentPeriod.high=价格;
currentPeriod.low=价格;
}
}
}

这是很多代码--您能缩小问题范围并澄清您的问题吗?我对代码感到抱歉,但问题是,问题没有本地化。据我所知,出现错误是因为函数调用调用了另一个函数,而另一个函数调用了另一个函数,依此类推。这正是这里发生的事情,除了完全是故意的。使用BigDecimal意味着函数中有大量函数调用,我不知道如何缩小范围。我想我的问题是,有没有什么具体的方法来避免超过调用堆栈的大小?一种基于函数调用函数的语言应该有一些常见的方法来避免这个问题。在普通的JavaScript编码中不应该遇到这个问题。我想你可能在什么地方有个虫子。使用节点调试器查看是否无法缩小范围。