1

注意:我在此处附加了一个链接到我的程序的(半)工作版本。

我正在使用 Finnhub 和 P5.js 库编写一个股票图表程序。

我在调试代码以根据股票的总价值范围生成 Y 轴值时遇到问题。调用窗口/全局变量 (window.yAxisRange) 时,在其中调用变量的 for 循环似乎在将任何内容写入所述变量之前正在运行。

具体来说,控制台显示我为检查 yAxisRange 变量的值而编写的 console.log() 代码显示了两次(该特定循环的每次迭代一次)。第一个实例显示返回的 NaN 值。浏览器视图中的图表给出了一个很好的问题示例,因为似乎生成了可行的数字,但由于某种原因,NaN 值覆盖在它们之上。

我很困惑为什么我收到一个 NaN 值,以及为什么调用 window.yAxisRange 的循环运行得这么早。

我的代码如下(我为任何差异道歉,因为我花了一些时间调整它):

import finnhub from 'https://cdn.skypack.dev/finnhub';

// Finance API Function Call Below
const api_key = finnhub.ApiClient.instance.authentications['api_key'];
api_key.apiKey = "c5cam0iad3ib55bb0ajg"
const finnhubClient = new finnhub.DefaultApi()

let stockTicker = prompt("Please enter the symbol of the stock to chart:");

var yAxisAutoRange = 0

finnhubClient.stockCandles(
  stockTicker, "D", ((Math.trunc(Date.now() / 1000)) - 8640000), Date.now(),
  (error, data, response) => {
    console.log("The maximum stock value of the timeframe is: " + max(Object.values(data.h)));

    console.log("The minimum stock value of the timeframe is: " + min(Object.values(data.l)));

    console.log("The values of the stock's highs are: " + (Object.values(data.h)))

    console.log("The values of the stock's lows are: " + (Object.values(data.l)))

    let yAxisRangeUpper = (max(Object.values(data.h))) + (max(Object.values(data.h)) - min(Object.values(data.l)))
    let yAxisRangeLower = (min(Object.values(data.l))) - (max(Object.values(data.h)) - min(Object.values(data.l)))

    let yAxisRange = (max(Object.values(data.h)) - min(Object.values(data.l))) / 2
    window.yAxisRange = Math.trunc(yAxisRange)
    console.log("yAxis Range: " + window.yAxisRange);

    console.log("range maximum value : " + yAxisRangeUpper);
    console.log("range minimum value : " + yAxisRangeLower);

    window.yAxisAutoRange = Math.trunc(yAxisRangeUpper / 23);
    console.log("yAxisAutoRange: " + yAxisRange);

    let xAxisDayArray = []
    let dayArrayLoop = data.t.length
    let dayArrayLoop2 = data.t.length

    window.xAxisDayArray = []
    window.dayArrayLoop = data.t.length
    window.dayArrayLoop2 = data.t.length

    for (dayArrayLoop = dayArrayLoop; dayArrayLoop > dayArrayLoop2 - 44; dayArrayLoop = dayArrayLoop - 1) {
      xAxisDayArray[dayArrayLoop] = JSON.stringify(new Date(data.t[dayArrayLoop - 1] * 1000));
      xAxisDayArray[dayArrayLoop] = parseInt(xAxisDayArray[dayArrayLoop].slice(9, 11))
      window.xAxisDayArray[dayArrayLoop] = xAxisDayArray[dayArrayLoop]
      //console.log("Data point " + dayArrayLoop + "for date " + xAxisDayArray[dayArrayLoop])
    }
  }
);

var month = 0

// P5 Chart Background Below
globalThis.setup = function() {
  createCanvas(1080, 768);
  background(220);

  const months = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];

  const d = new Date();
  window.month = months[d.getMonth()];
  console.log(month)

  const day = new Date();
  day.getDate();

  textSize(18)
  text(window.month.slice(0, 3), 1030, 755);
}

globalThis.draw = function() {
  // rect(yAxisAutoRange, 300, 10, 100);

  let i = 20;
  for (i = 20; i < 1020; i = i + 25) {

    let y = 0;

    for (line(1025, 0, 1025, 768), y = 0; y < 730; y = y + 15) {
      stroke(140, 25);
      line(i, y, (i + 10), y)
    };
  }

  let z = 10;
  for (z = 10; z < 730; z = z + 15) {

    let x = 25;

    for (line(0, 730, 1080, 730), x = 25; x < 1026; x = x + 25) {
      line(x, z, x, (z + 10))
    }
  }

  let yAxisLine = 730
  let yAxisIndLocate = 710
  let yAxisMultiple = 1
  let yAxisNum = String(parseInt(window.yAxisAutoRange * yAxisMultiple))

  // May need to simplify loop structure so as to cancel recurring drawing functions
  for (yAxisLine = 705, yAxisIndLocate = 710, yAxisMultiple = 1; yAxisLine > 14, yAxisIndLocate > 14, yAxisMultiple < 24; yAxisLine = yAxisLine - 30, yAxisIndLocate = yAxisIndLocate - 30, yAxisMultiple = yAxisMultiple + 1) {

    console.log("Y Axis Auto Range = " + window.yAxisAutoRange);

    stroke(51)
    line(1025, yAxisLine, 1040, yAxisLine);
    textSize(18);
    //console.log("Endless Loop Test " + yAxisNum) //window.yAxisAutoRange not registerring
    //console.log("Y Axis Ind = " + window.yAxisRange);
    text(window.yAxisRange / 23 * yAxisMultiple, 1045, yAxisIndLocate);
  }

  let xAxisLine = 1000
  let xAxisIndLocate = 0

  for (xAxisLine = 1000, window.dayArrayLoop = window.dayArrayLoop; xAxisLine > 24, window.dayArrayLoop > window.dayArrayLoop2 - 41; xAxisLine = xAxisLine - 25, window.dayArrayLoop = window.dayArrayLoop - 1) {
    stroke(51)
    line(xAxisLine, 730, xAxisLine, 745);
    //console.log(xAxisLine);
    text(parseInt(window.xAxisDayArray[dayArrayLoop]), xAxisLine - 5, 760)

    noLoop()
  }
}

4

1 回答 1

1

首先,这里是如何让这段代码在堆栈溢出时作为片段运行(添加调试):

<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/p5.js"></script>

<script type="module">
import finnhub from 'https://cdn.skypack.dev/finnhub';

// Finance API Function Call Below
const api_key = finnhub.ApiClient.instance.authentications['api_key'];
api_key.apiKey = "c5cam0iad3ib55bb0ajg"
const finnhubClient = new finnhub.DefaultApi()

let stockTicker = prompt("Please enter the symbol of the stock to chart:");

var yAxisAutoRange = 0;
console.log('module scope yAxisAutoRange: ' + yAxisAutoRange);
console.log('window.yAxisAutoRange: ' + window.yAxisAutoRange);

console.log("Requesting data for " + stockTicker);
finnhubClient.stockCandles(
  stockTicker, "D", ((Math.trunc(Date.now() / 1000)) - 8640000), Date.now(),
  (error, data, response) => {
    console.log("The maximum stock value of the timeframe is: " + max(Object.values(data.h)));
    console.log("The minimum stock value of the timeframe is: " + min(Object.values(data.l)));
    console.log("The values of the stock's highs are: " + (Object.values(data.h)))
    console.log("The values of the stock's lows are: " + (Object.values(data.l)))

    let yAxisRangeUpper = (max(Object.values(data.h))) + (max(Object.values(data.h)) - min(Object.values(data.l)))
    let yAxisRangeLower = (min(Object.values(data.l))) - (max(Object.values(data.h)) - min(Object.values(data.l)))

    let yAxisRange = (max(Object.values(data.h)) - min(Object.values(data.l))) / 2
    window.yAxisRange = Math.trunc(yAxisRange)
    console.log("yAxis Range: " + window.yAxisRange);

    console.log("range maximum value : " + yAxisRangeUpper);
    console.log("range minimum value : " + yAxisRangeLower);

    window.yAxisAutoRange = Math.trunc(yAxisRangeUpper / 23);
    console.log("yAxisAutoRange: " + yAxisRange);

    let xAxisDayArray = []
    let dayArrayLoop = data.t.length
    let dayArrayLoop2 = data.t.length

    window.xAxisDayArray = []
    window.dayArrayLoop = data.t.length
    window.dayArrayLoop2 = data.t.length

    for (dayArrayLoop = dayArrayLoop; dayArrayLoop > dayArrayLoop2 - 44; dayArrayLoop = dayArrayLoop - 1) {
      xAxisDayArray[dayArrayLoop] = JSON.stringify(new Date(data.t[dayArrayLoop - 1] * 1000));
      xAxisDayArray[dayArrayLoop] = parseInt(xAxisDayArray[dayArrayLoop].slice(9, 11))
      window.xAxisDayArray[dayArrayLoop] = xAxisDayArray[dayArrayLoop]
      //console.log("Data point " + dayArrayLoop + "for date " + xAxisDayArray[dayArrayLoop])
    }
  }
);

var month = 0

console.log("Declaring p5.js sketch");
// P5 Chart Background Below
globalThis.setup = function() {
  console.log("p5.js sketch setup");
  createCanvas(1080, 768);
  background(220);

  const months = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];

  const d = new Date();
  window.month = months[d.getMonth()];
  console.log(month)

  const day = new Date();
  day.getDate();

  textSize(18)
  text(window.month.slice(0, 3), 1030, 755);
  
  // Slow down the framerate so we don't spam the logs during debugging
  frameRate(5);
}

globalThis.draw = function() {
  console.log('p5.js draw');
  // rect(yAxisAutoRange, 300, 10, 100);

  let i = 20;
  for (i = 20; i < 1020; i = i + 25) {
    let y = 0;
    for (line(1025, 0, 1025, 768), y = 0; y < 730; y = y + 15) {
      stroke(140, 25);
      line(i, y, (i + 10), y)
    };
  }

  let z = 10;
  for (z = 10; z < 730; z = z + 15) {
    let x = 25;
    for (line(0, 730, 1080, 730), x = 25; x < 1026; x = x + 25) {
      line(x, z, x, (z + 10))
    }
  }

  let yAxisLine = 730
  let yAxisIndLocate = 710
  let yAxisMultiple = 1
  let yAxisNum = String(parseInt(window.yAxisAutoRange * yAxisMultiple))

  console.log("Y Axis Auto Range = " + window.yAxisAutoRange);
    
  // May need to simplify loop structure so as to cancel recurring drawing functions
  for (yAxisLine = 705, yAxisIndLocate = 710, yAxisMultiple = 1; yAxisLine > 14, yAxisIndLocate > 14, yAxisMultiple < 24; yAxisLine = yAxisLine - 30, yAxisIndLocate = yAxisIndLocate - 30, yAxisMultiple = yAxisMultiple + 1) {
    stroke(51)
    line(1025, yAxisLine, 1040, yAxisLine);
    textSize(18);
    //console.log("Endless Loop Test " + yAxisNum) //window.yAxisAutoRange not registerring
    //console.log("Y Axis Ind = " + window.yAxisRange);
    text(window.yAxisRange / 23 * yAxisMultiple, 1045, yAxisIndLocate);
  }

  let xAxisLine = 1000
  let xAxisIndLocate = 0

  for (xAxisLine = 1000, window.dayArrayLoop = window.dayArrayLoop; xAxisLine > 24, window.dayArrayLoop > window.dayArrayLoop2 - 41; xAxisLine = xAxisLine - 25, window.dayArrayLoop = window.dayArrayLoop - 1) {
    stroke(51)
    line(xAxisLine, 730, xAxisLine, 745);
    //console.log(xAxisLine);
    text(parseInt(window.xAxisDayArray[dayArrayLoop]), xAxisLine - 5, 760)

    noLoop()
  }
}
</script>

因为您使用的是顶级导入,而 Stack Snippets 不支持它,所以您必须将所有 JavaScript 移动到 HTML 中(这有点令人讨厌,StackOverflow 应该可以解决这个问题)。

话虽如此,这里的基本问题是您正在对数据进行异步请求,然后立即初始化依赖于该数据(或至少依赖于从中计算的值)的 p5.js 草图。考虑以下控制台日志输出:

Requesting data for tsla
Declaring p5.js sketch
p5.js sketch setup
You just changed the value of "month", which was a p5 function. This could cause problems later if you're not careful.
0
p5.js draw
Y Axis Auto Range = undefined
... repeatedly
p5.js draw
Y Axis Auto Range = undefined
The maximum stock value of the timeframe is: 1243.49
The minimum stock value of the timeframe is: 813.35
The values of the stock's highs are: 820.25,843.21,...
The values of the stock's lows are: 813.35,822.35,...
yAxis Range: 215
range maximum value : 1673.63
range minimum value : 383.21
yAxisAutoRange: 215.07
p5.js draw
Y Axis Auto Range = 72

希望由此不言而喻,yAxisAutoRange最初是很自然的,undefined因此window.yAxisRange / 23 * yAxisMultipleNaN:因为计算它的代码还没有运行!

,此外,在 for 循环的条件表达式中使用运算符时要小心!false, truetruetrue, falsefalse。我不确定这就是你想要做的(也许你应该使用||逻辑或,或者&&逻辑与。

于 2022-01-22T10:05:10.033 回答