JS函数仅输出3次而非5次的问题排查求助
问题排查与代码优化请求
我正在做一个提升JS技能的练手项目,碰到了瓶颈:代码只计算前3组测试值,完全忽略testNumber4、testNumber5和testPrice4、testPrice5这最后两组。奇怪的是,不调用calculateKlineTimes函数时,console.log("1")能输出5次;调用该函数后,"1"只在控制台输出3次。我JS基础不算深,希望能得到问题排查的思路和代码优化的建议。
我的代码
const testNumber1 = 1700494030000; const testNumber2 = 1700494060000; const testNumber3 = 1700494090000; const testNumber4 = 1700494094000; const testNumber5 = 1700494095000; const testPrice1 = 100; const testPrice2 = 200; const testPrice3 = 300; const testPrice4 = 310; const testPrice5 = 320; let KlineCloseTimeArray = []; let KlineOpenTimeArray = []; let klineDataArray = []; let TestNumberArray = [testNumber1, testNumber2, testNumber3, testNumber4, testNumber5]; let TestPriceArray = [testPrice1, testPrice2, testPrice3, testPrice4, testPrice5]; let combinedArray = TestNumberArray.map((testNumber, index) => { return { e: testNumber, c: TestPriceArray[index] }; }); // Function to create Kline data function createKlineData(Time, openTime, closeTime, closePrice) { return { "E": Time, "k": { "t": openTime, "T": closeTime, "s": "BTCUSDT", "i": "1m", "o": "testing", //openPrice.toString(), "c": closePrice.toString(), }, }; }; // Calculation to determin the t and T value open CandleStick value and close CandelStick value // Function to calculate open and close times function calculateKlineTimes(currentTestNumber, currentTestPrice) { let KlineOpenTime = null; let KlineCloseTime = null; // Check downwards for (let i = currentTestNumber - 10000; i >= 0; i -= 10000) { if (i % 60000 === 0) { KlineOpenTime = i; break; } }; // Check upwards for (let i = currentTestNumber + 10000;; i += 10000) { if (i % 60000 === 0) { KlineCloseTime = +i - 1; break; } }; if (klineDataArray.length > 0) { LastKlineDataArray = klineDataArray[klineDataArray.length - 1]; console.log(LastKlineDataArray) console.log("testing") }; KlineCloseTimeArray.push(KlineCloseTime); KlineOpenTimeArray.push(KlineOpenTime); if (klineDataArray.length > 0) { if (KlineOpenTime > LastKlineDataArray.k.t) { klineDataArray.push(createKlineData(currentTestNumber, LastKlineDataArray.k.t, LastKlineDataArray.k.T, currentTestPrice)); } }; // Create Kline data and print it const klineData = createKlineData(currentTestNumber, KlineOpenTime, KlineCloseTime, currentTestPrice); console.log(klineData) klineDataArray.push(klineData); //console.log(JSON.stringify(klineData, null, 2)); //console.log(klineDataArray); console.log("::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::"); } // Calculate Kline times for each combined test number and price for (let item of combinedArray) { calculateKlineTimes(item.e, item.c); console.log("1") } console.log("Minimum Requirement Array:", KlineOpenTimeArray); console.log("Maximum Requirement Array:", KlineCloseTimeArray);
我尝试过单独执行循环,console.log("1")能输出5次,但调用函数后仅输出3次。我也修改过代码,但问题未解决,当前版本代码相对简洁。
问题根源分析
- 无限循环卡死:计算
KlineCloseTime的向上循环没有终止条件,处理testNumber4和testNumber5时,这个循环会无限运行——这两个时间戳每次加10000后都无法被60000整除,永远找不到符合条件的i,直接导致后续代码无法执行,所以"1"只输出3次。 - 全局变量污染:
LastKlineDataArray没有用let/const声明,变成了全局变量,容易引发意外的逻辑错误。 - K线数据逻辑错误:当
KlineOpenTime > LastKlineDataArray.k.t时,会往数组里重复添加K线数据,不符合同一根K线应该更新收盘价而非新增的规则。
代码优化方案
修复核心问题
用数学方法替代循环计算K线时间,既高效又避免死循环:
- 开盘时间:
Math.floor(timestamp / 60000) * 60000(向下取整到最近的1分钟整点) - 收盘时间:开盘时间 + 60000 - 1(1分钟K线的收盘时间为开盘后59分59秒999毫秒)
优化后的完整代码
const testNumber1 = 1700494030000; const testNumber2 = 1700494060000; const testNumber3 = 1700494090000; const testNumber4 = 1700494094000; const testNumber5 = 1700494095000; const testPrice1 = 100; const testPrice2 = 200; const testPrice3 = 300; const testPrice4 = 310; const testPrice5 = 320; const KlineCloseTimeArray = []; const KlineOpenTimeArray = []; const klineDataArray = []; const TestNumberArray = [testNumber1, testNumber2, testNumber3, testNumber4, testNumber5]; const TestPriceArray = [testPrice1, testPrice2, testPrice3, testPrice4, testPrice5]; const combinedArray = TestNumberArray.map((timestamp, index) => ({ e: timestamp, c: TestPriceArray[index] })); // 创建K线数据 function createKlineData(timestamp, openTime, closeTime, price) { return { "E": timestamp, "k": { "t": openTime, "T": closeTime, "s": "BTCUSDT", "i": "1m", "o": "testing", "c": price.toString(), }, }; }; // 计算K线开收盘时间并处理数据 function calculateKlineTimes(timestamp, price) { // 用数学方法计算开收盘时间,替代循环 const openTime = Math.floor(timestamp / 60000) * 60000; const closeTime = openTime + 60000 - 1; KlineCloseTimeArray.push(closeTime); KlineOpenTimeArray.push(openTime); // 检查是否已有同根K线,有则更新收盘价,无则新增 const existingKlineIndex = klineDataArray.findIndex(item => item.k.t === openTime); if (existingKlineIndex !== -1) { klineDataArray[existingKlineIndex].E = timestamp; klineDataArray[existingKlineIndex].k.c = price.toString(); } else { const klineData = createKlineData(timestamp, openTime, closeTime, price); klineDataArray.push(klineData); } console.log("当前K线数据:", klineDataArray[klineDataArray.length - 1]); console.log("--------------------------------------------------"); } // 遍历处理所有测试数据 for (const item of combinedArray) { calculateKlineTimes(item.e, item.c); console.log("1"); } console.log("开盘时间数组:", KlineOpenTimeArray); console.log("收盘时间数组:", KlineCloseTimeArray); console.log("最终K线数据数组:", klineDataArray);
额外优化建议
- 尽量用
const声明不需要重新赋值的变量,避免意外修改 - 给函数、变量起更清晰的名字(比如
currentTestNumber改成timestamp,currentTestPrice改成price) - 把K线周期(60000)抽成常量,方便后续切换不同周期的K线
内容的提问来源于stack exchange,提问作者Schtraded
相关产品推荐
相关产品推荐

