You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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次。我也修改过代码,但问题未解决,当前版本代码相对简洁。


问题根源分析

  1. 无限循环卡死:计算KlineCloseTime的向上循环没有终止条件,处理testNumber4和testNumber5时,这个循环会无限运行——这两个时间戳每次加10000后都无法被60000整除,永远找不到符合条件的i,直接导致后续代码无法执行,所以"1"只输出3次。
  2. 全局变量污染:LastKlineDataArray没有用let/const声明,变成了全局变量,容易引发意外的逻辑错误。
  3. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 19:24:53