英文:
Problem printing text that has just been written
问题
I'm making a simple HTML webpage with some JavaScript. I take information from a JSON file, and with the help of JavaScript, I format the text and prepare it to export to a CSV file.
The problem comes when I write the text on the page, and after I try to read it. It gives me an Empty string, so I can't export it.
For testing, I'm just writing the output with console.log
, but I'm not getting the response that I expect.
JavaScript
document.addEventListener('DOMContentLoaded', function () {
convertData();
});
function convertData() {
fetch('info.json')
.then(response => response.json())
.then(data => showData(data))
.then(print())
.catch(error => console.error('Error:', error));
}
function showData(data) {
const container = document.getElementById("container");
for (var i = 0; i < data["data"].length; i++) {
var obj = data["data"][i];
container.innerHTML += "<br>" + obj["field1"] + "; " + obj["field2"] + "; ";
}
}
function print() {
const container = document.getElementById("container");
const data = container.innerHTML;
console.log(data);
}
HTML
<!DOCTYPE html>
<html>
<body>
<div id="container"></div>
</body>
</html>
When I use container.innerHTML += "....."
, it shows me the content correctly, but when I print it, it doesn't show properly.
I can't use TimeOuts
, because I don't know how long it can take. It can be 3 seconds on the first time and 40 seconds on the second one.
英文:
I'm making a simple HTML webpage with some JavaScript. I take information from a JSON file, and with help of JavaScript, I format the text and prepare it to export to a CSV file.
The problem comes when I write the text on the page, and after I try to read it. It gives me an Empty string, so I can't export it.
For testing, I'm just writing the output with console.log
, but I'm not getting the response that I expect.
JavaScript
document.addEventListener('DOMContentLoaded', function () {
convertData();
});
function convertData() {
fetch('info.json')
.then(response => response.json())
.then(data => showData(data))
.then(print())
.catch(error => console.error('Error:', error));
}
function showData(data) {
const container = document.getElementById("container");
for (var i = 0; i < data["data"].length; i++) {
var obj = data["data"][i];
container.innerHTML += "<br>" + obj["field1"] + "; " + obj["field2"] + "; "
}
}
function print() {
const container = document.getElementById("container");
const data = container.innerHTML;
console.log(data);
}
HTML
<!DOCTYPE html>
<html>
<body>
<div id="container"></div>
</body>
</html>
When I use container.innerHTML += "....."
, it shows me the content correctly, but when I print it, it doesn't show properly.
I can't use TimeOuts
, because I don't know how long it can take. It can be 3 seconds on the first time and 40 seconds con the second one.
答案1
得分: 1
The main problem is that you're immediately invoking print
. What you're essentially doing is calling print
right away (before the fetch request is even sent) and passing the return value of print (undefined
) to the then
call. What you want to do is pass a function as a parameter so that function is called when the previous promises are resolved.
Just change
function convertData() {
fetch('info.json')
.then(response => response.json())
.then(data => showData(data))
.then(print())
.catch(error => console.error('Error:', error));
}
To
function convertData() {
fetch('info.json')
.then(response => response.json())
.then(data => showData(data))
.then(print)
.catch(error => console.error('Error:', error));
}
Or
function convertData() {
fetch('info.json')
.then(response => response.json())
.then(data => showData(data))
.then(() => print())
.catch(error => console.error('Error:', error));
}
It's also a bit unsafe to use a plain load listener without checking if the respective load event has already triggered. What I like to do is:
if (document.readyState === "complete") convertData();
else addEventListener("load", convertData);
Here is a functional example with a mock fetch:
<!DOCTYPE html>
<html>
<body>
<div id="container">
</div>
</body>
</html>
<script>
function mockFetch() {
const data = {
data: [{
field1: "foo",
field2: "bar"
},
{
field1: "foobar",
field2: "_"
}
]
};
const jsonData = JSON.stringify(data);
const response = new Response(jsonData);
return Promise.resolve(response);
}
if (document.readyState === "complete") convertData();
else addEventListener("load", convertData);
function convertData() {
mockFetch()
.then(response => response.json())
.then(showData)
.then(print)
.catch(error => console.error(error));
}
function showData(data) {
const container = document.getElementById("container");
for (let i = 0; i < data["data"].length; i++) {
let obj = data["data"][i];
container.innerHTML += "<br>" + obj["field1"] + "; " + obj["field2"] + "; ";
}
}
function print() {
const container = document.getElementById("container");
const data = container.innerHTML;
console.log(data);
}
</script>
Some other notes:
It's safer to use let
or const
instead of var
inside for
loops link.
You can replace obj["field1"]
with obj.field1
; you can access it normally. You should reserve the ["param"]
notation for when the key is not a valid property name (i.e., contains spaces, starts with numbers, contains invalid characters...).
英文:
The main problem is that you're immediately invoking print
. What you're essentially doing is calling print
right away (before the fetch request is even sent) and passing the return value of print (undefined
) to the then
call. What you want to do is pass a function as a paramter so that function is called when the previous promises are resolved.
Just change
function convertData() {
fetch('info.json')
.then(response => response.json())
.then(data => showData(data))
.then(print())
.catch(error => console.error('Error:', error));
}
To
function convertData() {
fetch('info.json')
.then(response => response.json())
.then(data => showData(data))
.then(print)
.catch(error => console.error('Error:', error));
}
Or
function convertData() {
fetch('info.json')
.then(response => response.json())
.then(data => showData(data))
.then(() => print())
.catch(error => console.error('Error:', error));
}
It's also a bit unsafe to use a plain load listener without checking if the respective load event has already triggered, what I like to do is:
if (document.readyState === "complete") convertData();
else addEventListener("load", convertData);
Here is a functional example with a mock fetch:
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-js -->
function mockFetch() {
const data = {
data: [{
field1: "foo",
field2: "bar"
},
{
field1: "foobar",
field2: "_"
}
]
};
const jsonData = JSON.stringify(data);
const response = new Response(jsonData);
return Promise.resolve(response);
}
if (document.readyState === "complete") convertData();
else addEventListener("load", convertData);
function convertData() {
mockFetch()
.then(response => response.json())
.then(showData)
.then(print)
.catch(error => console.error(error));
}
function showData(data) {
const container = document.getElementById("container");
for (var i = 0; i < data["data"].length; i++) {
var obj = data["data"][i];
container.innerHTML += "<br>" + obj["field1"] + "; " + obj["field2"] + "; "
}
}
function print() {
const container = document.getElementById("container");
const data = container.innerHTML;
console.log(data);
}
<!-- language: lang-html -->
<!DOCTYPE html>
<html>
<body>
<div id="container">
</div>
</body>
</html>
<!-- end snippet -->
Some other notes:
It's safer to use to let
or const
instead of var
inside for
loops link.
You can replace obj["field1"]
with obj.field1
, you can accesss it normally, you should reserve the ["param"]
notation for when the key is not a valid property name (i.e. contains spaces, starts with numbers, contains invalid characters...)
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论