我正在尝试在我的
chart.ejs
文件中渲染 Plotly OHLC 图,并将名为 result
的变量传递给它。但是,当我尝试使用 EJS 模板将 result
包含在 chart.ejs
文件中时,该图不会显示。我还尝试使用 <script>
标签进行逻辑,但绘图仍然不显示。我制作了另一个文件chart.js
来包含有关情节的逻辑,但我不确定如何使其工作。
可能导致此问题的原因是什么?如何使用 EJS 模板中的结果数据成功渲染 Plotly OHLC 图?
index.js:
import express from "express";
import axios from "axios";
const app = express();
const port = 3000;
app.use(express.static("public"));
app.set("view engine", "ejs"); // Set EJS as the view engine
const base_url = "https://api.coingecko.com/api/v3";
app.get("/", (req, res) => {
res.render("index.ejs", { result: null, error: null });
});
app.get("/ohlc", async (req, res) => {
const { id, currency, days } = req.query;
if (!id || !currency || !days) {
return res
.status(400)
.json({ error: "Please provide id, currency, and days parameters." });
}
try {
const ohlc_result = await axios.get(`${base_url}/coins/${id}/ohlc`, {
params: {
vs_currency: currency,
days: days,
},
});
let day = [];
let open = [];
let high = [];
let low = [];
let close = [];
for (let i = 0; i < ohlc_result.data.length; i++) {
const unix_timestamp = ohlc_result.data[i][0];
const date = new Date(unix_timestamp);
const formattedDate = date.toISOString().split('T')[0];
if (!day.includes(formattedDate)) {
day.push(formattedDate);
open.push(ohlc_result.data[i][1]);
high.push(ohlc_result.data[i][2]);
low.push(ohlc_result.data[i][3]);
close.push(ohlc_result.data[i][4]);
}
}
// Create the OHLC trace
const result = {
x: day,
open: open,
high: high,
low: low,
close: close,
type: "ohlc",
increasing: { line: { color: "#17BECF" } },
decreasing: { line: { color: "#7F7F7F" } },
};
console.log("OHLC Result:", ohlc_result.data);
console.log("Formatted Result:", result);
res.render("chart.ejs", { result: result });
} catch (error) {
console.log(error.message);
res.status(500).send(error.message);
}
});
app.listen(port, () => {
console.log(`Server is running on port ${port}`);
});
chart.js:
const trace = {
x: result.x,
open: result.open,
high: result.high,
low: result.low,
close: result.close,
type: "ohlc",
increasing: { line: { color: "#17BECF" } },
decreasing: { line: { color: "#7F7F7F" } },
};
const layout = {
title: "OHLC Chart",
dragmode: "zoom",
xaxis: {
title: "Date",
type: "date",
},
yaxis: {
title: "Price",
type: "linear",
},
};
Plotly.newPlot("ohlc-result-div", [trace], layout);
图表.ejs:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>CryptoLens</title>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">
<link rel="stylesheet" href="styles/main.css">
<script src='https://cdn.plot.ly/plotly-2.35.2.min.js'></script>
<!-- <script src="/chart.js" defer></script> -->
</head>
<body>
<h1>OHLC Chart</h1>
<!-- THE FOLLOWING DOES NOT WORK -->
<!-- <script>
const trace = {
x: result.x,
open: result.open,
high: result.high,
low: result.low,
close: result.close,
type: "ohlc",
increasing: { line: { color: "#17BECF" } },
decreasing: { line: { color: "#7F7F7F" } },
};
const layout = {
title: "OHLC Chart",
dragmode: "zoom",
xaxis: {
title: "Date",
type: "date",
},
yaxis: {
title: "Price",
type: "linear",
},
};
Plotly.newPlot("ohlc-result", [trace], layout);
</script> -->
<div id="ohlc-result-div"><!-- Plotly chart will be drawn inside this DIV --></div>
</body>
</html>
我知道将
result
发送到 chart.ejs
时存在一些问题,我只是不确定是什么。
这里的问题是如何使用传递给渲染引擎的变量。
您传递给
render()
函数的变量仅在渲染期间可用,并且仅适用于 EJS 标签 <% ... %>
中的代码。您可以在这个答案上阅读有关 EJS 变量的更多信息。
这意味着在
<script>
中没有定义 result
变量。据我所知,您有两个选择:
将 EJS 变量传递给脚本
可能更快、更简单的解决方案是将变量传递给脚本标记。从技术上讲,它就像
一样简单<script>
let resultInScript = <%= result %>
...
但有一些注意事项。首先也是最重要的,大多数 IDE 都会将其显示为错误,即使它会执行。这只是因为它不知道
<script>
内的 EJS 语法,并且可以通过使用任何字符串分隔符("
引号、'
撇号、`
反引号)来避免它,如下所示:
<script>
let resultInScript = "<%= result %>"
...
下一个问题是对象。回顾上一期,如果我们想一想,无论EJS标签中的变量到底是什么,它在javascript端总是一个字符串。因此,如果我们像之前那样简单地传递
result
,那么 resultInScript
就只是 [object Object]
作为字符串。所以所有这一切的最终形式看起来像
<script>
let resultInScript = JSON.parse("<%= JSON.stringify(result) %>");
...
AJAX 请求服务器
另一种解决方案是在页面加载时向服务器发送异步请求并获取数据。 因此,您可以在服务器上创建一条路由,例如
app.get('/ohcl/data'...
,并在页面加载时立即向服务器发送请求。根据数据的重要程度,您可以仅使用数据作为查询参数发出 GET 请求,也可以使用正文中的数据发出 POST 请求。这并不是说它超级安全,但至少没有将它们作为查询参数。
这也将使您的页面加载时间更短,并且数据/图表的加载速度类似,具体取决于数据检索的速度,最多几秒,最多几毫秒。
希望对你有帮助,如有不清楚的地方请随时询问。