表单提交后,函数运行很快, chart.js 出现一秒钟然后消失
After form submit, function runs quickly and chart.js shows up for a second then goes away
我有一个 Javascript 项目,我从 API 来源接收 Covid-19 数据。用户输入他们希望查看数据的国家/地区(从 2020 年 3 月到今天),然后使用 chart.js 将数据绘制到屏幕上。我在用户输入国家/地区的输入字段中添加了一个事件侦听器,并以这种方式检索数据。但是,当我调用我的函数来绘制数据图 ( graphIt() ) 时,该函数发生一秒钟然后消失。我理解为什么会发生这种情况,因为该函数只被调用一次,所以它很快就完成了。但是,我怎样才能让 chart.js 一直保持下去呢?我会把代码的重要部分放在这里!
index.html
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.3.0/Chart.min.js"></script>
<script src="{% static 'viewCasesChart/index.js' %}"></script>
<div id="banner">
<div id="banner_details">
<h2>CoData</h2>
</div>
</div>
<div id="one_line">
<div id="main_title">
<h1>Covid-19 Data</h1>
</div>
<div id="user_query_data">
<form id="country_form">
<input type="text" placeholder="Country" id="country">
<input type="submit" value="Search">
</form>
</div>
</div>
<div id="confirmed_graph">
<canvas id="myChart" height="500" width="300"></canvas>
</div>
index.js
document.addEventListener('DOMContentLoaded', () => {
//make a global variable and put default value into it
var country = "Italy";
document.getElementById('country_form').addEventListener('submit', () => {
var delayInMilliseconds = 100000; //
country = document.getElementById('country').value;
console.log("test 1", country);
graphit();
})
async function graphit() {
document.getElementById('myChart').style.display = "block";
const dataset = await dataToGraph();
console.log("dataset.xs", dataset.xs);
console.log("dataset.ys", dataset.ys);
const ctx = document.getElementById('myChart').getContext('2d');
const myChart = new Chart(ctx, {
type: 'line',
data: {
labels: dataset.xs,
datasets: [{
label: `Covid 19 Confirmed cases in ${country}`,
data: dataset.ys,
backgroundColor: ['rgba(255, 99, 132, 0.2)'],
borderColor: ['rgba(255, 99, 132, 1)'],
borderWidth: 1,
fill: false,
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
scales: {
yAxes: [{
scaleLabel: {
display: true,
labelString: 'Confirmed Cases'
}
}],
xAxes: [{
scaleLabel: {
display: true,
labelString: 'Date'
}
}],
}
}
});
};
async function dataToGraph() {
const xs = [];
const ys = [];
var today = new Date();
var dd = String(today.getDate()).padStart(2, '0');
var mm = String(today.getMonth() + 1).padStart(2, '0'); //January is 0!
var yyyy = today.getFullYear();
today = yyyy + '-' + mm + '-' + dd;
console.log("test 2", country);
fetch(`https://webhooks.mongodb-stitch.com/api/client/v2.0/app/covid-19-qppza/service/REST-API/incoming_webhook/countries_summary?country=${country}&min_date=2020-04-22&max_date=${today}`)
.then(response => response.json())
.then(days => {
days.forEach(day => {
ys.push(day.confirmed);
xs.push(day.date);
})
})
console.log("xs", xs);
console.log("ys", ys);
console.log(`https://webhooks.mongodb-stitch.com/api/client/v2.0/app/covid-19-qppza/service/REST-API/incoming_webhook/countries_summary?country=${country}&min_date=2020-04-22&max_date=${today}`);
return { xs, ys };
};
}); // Edit: final closing brackets were missing
event.preventDefault()
在表单提交时丢失:
您的图表未出现的原因是您的表单提交中缺少 event.preventDefault()
语句。因此,您的表单正在发送 HTTP 请求(默认操作)而不是执行您的代码。
我编辑了你的代码:
- 已添加
event.preventDefault()
在表单提交时
- 在函数外声明变量以避免重复声明
- 消除了
async
功能,因为 fetch()
是一个 Promise(已经像异步回调一样工作,等待来自服务器的响应)
- 重新排列顺序:
首先在表单提交时调用 dataToGraph()
(使用 fetch()
获取数据)
然后,当 fetch()
-API 返回数据(异步)时,调用 graphit()
- 重新分配数据到您的图表(x 轴和 y 轴数据)和顶部标签,然后
update()
图表
- 为 chart.js 的最终版本改编代码 v3.5.1 以提高性能(v3.x 不兼容 v2.x):
- 为意大利
dataToGraph()
加载初始数据
运行 代码片段 并输入一个国家 ('Italy', 'G德国', ....)
(区分大小写:第一个字母必须是大写字母)
// define all variables here outside functions
// in order to avoid re-assigning multiple times
let xs = [];
let ys = [];
let dataset = {};
dataset.xs = xs;
dataset.ys = ys;
let country = "Italy";
let today = new Date();
let dd = String(today.getDate()).padStart(2, '0');
let mm = String(today.getMonth() + 1).padStart(2, '0'); //January is 0!
let yyyy = today.getFullYear();
today = yyyy + '-' + mm + '-' + dd;
const delayInMilliseconds = 100000;
const ctx = document.getElementById('myChart').getContext('2d');
const myChart = new Chart(ctx, {
type: 'line',
data: {
labels: dataset.xs,
datasets: [{
label: `Covid 19 Confirmed cases in ${country}`,
data: dataset.ys,
backgroundColor: ['rgba(255, 99, 132, 0.2)'],
borderColor: ['rgba(255, 99, 132, 1)'],
borderWidth: 1,
fill: false,
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
scales: {
yAxes: { // <-- axis is not array '[{' anymore, now object '{'
scaleLabel: {
display: true,
labelString: 'Confirmed Cases'
}
},
xAxes: { // <-- axis is not array '[{' anymore, now object '{'
scaleLabel: {
display: true,
labelString: 'Date'
}
}
}
}
});
// Load initial data for Italy
document.getElementById('country').value = country;
dataToGraph();
// here goes your Event-Listener with function as argument;
document.getElementById('country_form').addEventListener('submit', dataToGraph);
function dataToGraph(event) {
if (event) event.preventDefault(); // <-- this was missing
country = document.getElementById('country').value;
// console.log("test 1", country);
// give feedback to user that data is loading in background
myChart.data.datasets[0].label = `loading ... ${country}`;
myChart.update();
// set all variables to empty again:
xs = [];
ys = [];
dataset = {};
dataset.xs = xs;
dataset.ys = ys;
// fetch() is a Promise, i.e. it is like an async callback already,
// hence no need to call async again.
fetch(`https://webhooks.mongodb-stitch.com/api/client/v2.0/app/covid-19-qppza/service/REST-API/incoming_webhook/countries_summary?country=${country}&min_date=2020-04-22&max_date=${today}`)
.then(response => response.json())
.then(days => {
days.forEach(day => {
ys.push(day.confirmed);
xs.push(day.date);
});
dataset.xs = xs;
dataset.ys = ys;
// console.log("xs", xs);
// console.log("ys", ys);
// console.log(`https://webhooks.mongodb-stitch.com/api/client/v2.0/app/covid-19-qppza/service/REST-API/incoming_webhook/countries_summary?country=${country}&min_date=2020-04-22&max_date=${today}`);
// console.log(dataset);
// now you can graph it
graphit();
})
//return { xs, ys };
};
function graphit() {
document.getElementById('myChart').style.display = "block";
// const dataset = dataToGraph();
// console.log("dataset.xs", dataset.xs);
// console.log("dataset.ys", dataset.ys);
// re-assign the datasets again (x- and y-axis)
myChart.data.labels = dataset.xs;
myChart.data.datasets[0].data = dataset.ys;
myChart.data.datasets[0].label = `Covid 19 Confirmed cases in ${country}`;
// now update your chart
myChart.update();
};
<!-- <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.3.0/Chart.min.js"></script> -->
<!-- get the latest version of Chart.js, now at v3.5.1 -->
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<div id="banner">
<div id="banner_details">
<h2>CoData</h2>
</div>
</div>
<div id="one_line">
<div id="main_title">
<h1>Covid-19 Data</h1>
</div>
<div id="user_query_data">
<form id="country_form">
<input type="text" placeholder="Country" id="country">
<input type="submit" value="Search">
</form>
</div>
</div>
<div id="confirmed_graph">
<canvas id="myChart" height="500" width="300"></canvas>
</div>
最后的注释:
您可能会考虑将 x: { type: 'time' ...
功能添加到您的图表中,这样可以更好地显示 x 坐标轴标签(日期)。有关更多详细信息,请参阅我的回答 chart.js time series。
顺便说一下:不错 API - 我喜欢
欢迎使用堆栈溢出
我有一个 Javascript 项目,我从 API 来源接收 Covid-19 数据。用户输入他们希望查看数据的国家/地区(从 2020 年 3 月到今天),然后使用 chart.js 将数据绘制到屏幕上。我在用户输入国家/地区的输入字段中添加了一个事件侦听器,并以这种方式检索数据。但是,当我调用我的函数来绘制数据图 ( graphIt() ) 时,该函数发生一秒钟然后消失。我理解为什么会发生这种情况,因为该函数只被调用一次,所以它很快就完成了。但是,我怎样才能让 chart.js 一直保持下去呢?我会把代码的重要部分放在这里!
index.html
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.3.0/Chart.min.js"></script>
<script src="{% static 'viewCasesChart/index.js' %}"></script>
<div id="banner">
<div id="banner_details">
<h2>CoData</h2>
</div>
</div>
<div id="one_line">
<div id="main_title">
<h1>Covid-19 Data</h1>
</div>
<div id="user_query_data">
<form id="country_form">
<input type="text" placeholder="Country" id="country">
<input type="submit" value="Search">
</form>
</div>
</div>
<div id="confirmed_graph">
<canvas id="myChart" height="500" width="300"></canvas>
</div>
index.js
document.addEventListener('DOMContentLoaded', () => {
//make a global variable and put default value into it
var country = "Italy";
document.getElementById('country_form').addEventListener('submit', () => {
var delayInMilliseconds = 100000; //
country = document.getElementById('country').value;
console.log("test 1", country);
graphit();
})
async function graphit() {
document.getElementById('myChart').style.display = "block";
const dataset = await dataToGraph();
console.log("dataset.xs", dataset.xs);
console.log("dataset.ys", dataset.ys);
const ctx = document.getElementById('myChart').getContext('2d');
const myChart = new Chart(ctx, {
type: 'line',
data: {
labels: dataset.xs,
datasets: [{
label: `Covid 19 Confirmed cases in ${country}`,
data: dataset.ys,
backgroundColor: ['rgba(255, 99, 132, 0.2)'],
borderColor: ['rgba(255, 99, 132, 1)'],
borderWidth: 1,
fill: false,
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
scales: {
yAxes: [{
scaleLabel: {
display: true,
labelString: 'Confirmed Cases'
}
}],
xAxes: [{
scaleLabel: {
display: true,
labelString: 'Date'
}
}],
}
}
});
};
async function dataToGraph() {
const xs = [];
const ys = [];
var today = new Date();
var dd = String(today.getDate()).padStart(2, '0');
var mm = String(today.getMonth() + 1).padStart(2, '0'); //January is 0!
var yyyy = today.getFullYear();
today = yyyy + '-' + mm + '-' + dd;
console.log("test 2", country);
fetch(`https://webhooks.mongodb-stitch.com/api/client/v2.0/app/covid-19-qppza/service/REST-API/incoming_webhook/countries_summary?country=${country}&min_date=2020-04-22&max_date=${today}`)
.then(response => response.json())
.then(days => {
days.forEach(day => {
ys.push(day.confirmed);
xs.push(day.date);
})
})
console.log("xs", xs);
console.log("ys", ys);
console.log(`https://webhooks.mongodb-stitch.com/api/client/v2.0/app/covid-19-qppza/service/REST-API/incoming_webhook/countries_summary?country=${country}&min_date=2020-04-22&max_date=${today}`);
return { xs, ys };
};
}); // Edit: final closing brackets were missing
event.preventDefault()
在表单提交时丢失:
您的图表未出现的原因是您的表单提交中缺少 event.preventDefault()
语句。因此,您的表单正在发送 HTTP 请求(默认操作)而不是执行您的代码。
我编辑了你的代码:
- 已添加
event.preventDefault()
在表单提交时 - 在函数外声明变量以避免重复声明
- 消除了
async
功能,因为fetch()
是一个 Promise(已经像异步回调一样工作,等待来自服务器的响应) - 重新排列顺序:
首先在表单提交时调用dataToGraph()
(使用fetch()
获取数据)
然后,当fetch()
-API 返回数据(异步)时,调用graphit()
- 重新分配数据到您的图表(x 轴和 y 轴数据)和顶部标签,然后
update()
图表 - 为 chart.js 的最终版本改编代码 v3.5.1 以提高性能(v3.x 不兼容 v2.x):
- 为意大利
dataToGraph()
加载初始数据
运行 代码片段 并输入一个国家 ('Italy', 'G德国', ....)
(区分大小写:第一个字母必须是大写字母)
// define all variables here outside functions
// in order to avoid re-assigning multiple times
let xs = [];
let ys = [];
let dataset = {};
dataset.xs = xs;
dataset.ys = ys;
let country = "Italy";
let today = new Date();
let dd = String(today.getDate()).padStart(2, '0');
let mm = String(today.getMonth() + 1).padStart(2, '0'); //January is 0!
let yyyy = today.getFullYear();
today = yyyy + '-' + mm + '-' + dd;
const delayInMilliseconds = 100000;
const ctx = document.getElementById('myChart').getContext('2d');
const myChart = new Chart(ctx, {
type: 'line',
data: {
labels: dataset.xs,
datasets: [{
label: `Covid 19 Confirmed cases in ${country}`,
data: dataset.ys,
backgroundColor: ['rgba(255, 99, 132, 0.2)'],
borderColor: ['rgba(255, 99, 132, 1)'],
borderWidth: 1,
fill: false,
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
scales: {
yAxes: { // <-- axis is not array '[{' anymore, now object '{'
scaleLabel: {
display: true,
labelString: 'Confirmed Cases'
}
},
xAxes: { // <-- axis is not array '[{' anymore, now object '{'
scaleLabel: {
display: true,
labelString: 'Date'
}
}
}
}
});
// Load initial data for Italy
document.getElementById('country').value = country;
dataToGraph();
// here goes your Event-Listener with function as argument;
document.getElementById('country_form').addEventListener('submit', dataToGraph);
function dataToGraph(event) {
if (event) event.preventDefault(); // <-- this was missing
country = document.getElementById('country').value;
// console.log("test 1", country);
// give feedback to user that data is loading in background
myChart.data.datasets[0].label = `loading ... ${country}`;
myChart.update();
// set all variables to empty again:
xs = [];
ys = [];
dataset = {};
dataset.xs = xs;
dataset.ys = ys;
// fetch() is a Promise, i.e. it is like an async callback already,
// hence no need to call async again.
fetch(`https://webhooks.mongodb-stitch.com/api/client/v2.0/app/covid-19-qppza/service/REST-API/incoming_webhook/countries_summary?country=${country}&min_date=2020-04-22&max_date=${today}`)
.then(response => response.json())
.then(days => {
days.forEach(day => {
ys.push(day.confirmed);
xs.push(day.date);
});
dataset.xs = xs;
dataset.ys = ys;
// console.log("xs", xs);
// console.log("ys", ys);
// console.log(`https://webhooks.mongodb-stitch.com/api/client/v2.0/app/covid-19-qppza/service/REST-API/incoming_webhook/countries_summary?country=${country}&min_date=2020-04-22&max_date=${today}`);
// console.log(dataset);
// now you can graph it
graphit();
})
//return { xs, ys };
};
function graphit() {
document.getElementById('myChart').style.display = "block";
// const dataset = dataToGraph();
// console.log("dataset.xs", dataset.xs);
// console.log("dataset.ys", dataset.ys);
// re-assign the datasets again (x- and y-axis)
myChart.data.labels = dataset.xs;
myChart.data.datasets[0].data = dataset.ys;
myChart.data.datasets[0].label = `Covid 19 Confirmed cases in ${country}`;
// now update your chart
myChart.update();
};
<!-- <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.3.0/Chart.min.js"></script> -->
<!-- get the latest version of Chart.js, now at v3.5.1 -->
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<div id="banner">
<div id="banner_details">
<h2>CoData</h2>
</div>
</div>
<div id="one_line">
<div id="main_title">
<h1>Covid-19 Data</h1>
</div>
<div id="user_query_data">
<form id="country_form">
<input type="text" placeholder="Country" id="country">
<input type="submit" value="Search">
</form>
</div>
</div>
<div id="confirmed_graph">
<canvas id="myChart" height="500" width="300"></canvas>
</div>
最后的注释:
您可能会考虑将 x: { type: 'time' ...
功能添加到您的图表中,这样可以更好地显示 x 坐标轴标签(日期)。有关更多详细信息,请参阅我的回答 chart.js time series。
顺便说一下:不错 API - 我喜欢
欢迎使用堆栈溢出