问题:刚刚写入的文本无法打印。

huangapple go评论93阅读模式
英文:

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(&#39;DOMContentLoaded&#39;, function () {
    convertData();
});

function convertData() {
    fetch(&#39;info.json&#39;)
    .then(response =&gt; response.json())
    .then(data =&gt; showData(data))
    .then(print())
    .catch(error =&gt; console.error(&#39;Error:&#39;, error));
}

function showData(data) {
    const container = document.getElementById(&quot;container&quot;);

    for (var i = 0; i &lt; data[&quot;data&quot;].length; i++) {
        var obj = data[&quot;data&quot;][i];

        container.innerHTML += &quot;&lt;br&gt;&quot; + obj[&quot;field1&quot;] + &quot;; &quot; + obj[&quot;field2&quot;] + &quot;; &quot;
    }
}

function print() {
    const container = document.getElementById(&quot;container&quot;);
    const data = container.innerHTML;
    console.log(data);   
}

HTML

&lt;!DOCTYPE html&gt;
&lt;html&gt;
  &lt;body&gt;
    &lt;div id=&quot;container&quot;&gt;&lt;/div&gt;
  &lt;/body&gt;
&lt;/html&gt;

When I use container.innerHTML += &quot;.....&quot;, 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(&#39;info.json&#39;)
    .then(response =&gt; response.json())
    .then(data =&gt; showData(data))
    .then(print())
    .catch(error =&gt; console.error(&#39;Error:&#39;, error));
}

To

function convertData() {
    fetch(&#39;info.json&#39;)
    .then(response =&gt; response.json())
    .then(data =&gt; showData(data))
    .then(print)
    .catch(error =&gt; console.error(&#39;Error:&#39;, error));
}

Or

function convertData() {
    fetch(&#39;info.json&#39;)
    .then(response =&gt; response.json())
    .then(data =&gt; showData(data))
    .then(() =&gt; print())
    .catch(error =&gt; console.error(&#39;Error:&#39;, 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 === &quot;complete&quot;) convertData();
else addEventListener(&quot;load&quot;, 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: &quot;foo&quot;,
field2: &quot;bar&quot;
},
{
field1: &quot;foobar&quot;,
field2: &quot;_&quot;
}
]
};
const jsonData = JSON.stringify(data);
const response = new Response(jsonData);
return Promise.resolve(response);
}
if (document.readyState === &quot;complete&quot;) convertData();
else addEventListener(&quot;load&quot;, convertData);
function convertData() {
mockFetch()
.then(response =&gt; response.json())
.then(showData)
.then(print)
.catch(error =&gt; console.error(error));
}
function showData(data) {
const container = document.getElementById(&quot;container&quot;);
for (var i = 0; i &lt; data[&quot;data&quot;].length; i++) {
var obj = data[&quot;data&quot;][i];
container.innerHTML += &quot;&lt;br&gt;&quot; + obj[&quot;field1&quot;] + &quot;; &quot; + obj[&quot;field2&quot;] + &quot;; &quot;
}
}
function print() {
const container = document.getElementById(&quot;container&quot;);
const data = container.innerHTML;
console.log(data);
}

<!-- language: lang-html -->

&lt;!DOCTYPE html&gt;
&lt;html&gt;
&lt;body&gt;
&lt;div id=&quot;container&quot;&gt;
&lt;/div&gt;
&lt;/body&gt;
&lt;/html&gt;

<!-- 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[&quot;field1&quot;] with obj.field1, you can accesss it normally, you should reserve the [&quot;param&quot;] notation for when the key is not a valid property name (i.e. contains spaces, starts with numbers, contains invalid characters...)

huangapple
  • 本文由 发表于 2023年7月20日 17:58:18
  • 转载请务必保留本文链接:https://go.coder-hub.com/76728725.html