最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How to create "li"s based on "fetch" result - Stack Overflow

programmeradmin3浏览0评论

I am trying to pull some data from this website by referring to their documentation at /dog-api/documentation/

I am trying to retrieve the list of dog breeds and create a list. I am using javaScript's "fetch"

let dog_list = [];
fetch('/api/breeds/list/all')
  .then(response => {
    if (response.ok) {
      return response.json();
    } else {
      throw new Error(response.statusText);
    }
  })
  .then(data => dog_list = data.message)
const container = document.getElementById("container");
for (dog in dog_list) {
  let li = document.createElement("li");
  let node = document.createTextNode(dog);
  li.appendChild(node);
  container.appendChild(li);
}
<!DOCTYPE html>
<html lang="en">

<head>
  <title>Dog Breed List</title>
</head>

<body>
  <ul id="container"></ul>
  <script src="dog_breed.js"></script>
</body>

</html>

I am trying to pull some data from this website by referring to their documentation at https://dog.ceo/dog-api/documentation/

I am trying to retrieve the list of dog breeds and create a list. I am using javaScript's "fetch"

let dog_list = [];
fetch('https://dog.ceo/api/breeds/list/all')
  .then(response => {
    if (response.ok) {
      return response.json();
    } else {
      throw new Error(response.statusText);
    }
  })
  .then(data => dog_list = data.message)
const container = document.getElementById("container");
for (dog in dog_list) {
  let li = document.createElement("li");
  let node = document.createTextNode(dog);
  li.appendChild(node);
  container.appendChild(li);
}
<!DOCTYPE html>
<html lang="en">

<head>
  <title>Dog Breed List</title>
</head>

<body>
  <ul id="container"></ul>
  <script src="dog_breed.js"></script>
</body>

</html>

I am having issues at the second "then" where I have no idea on how to convert the json object into array and display them as

  • dog1
  • dog2
  • dog3
Share Improve this question asked Mar 10, 2019 at 17:19 Chai Chong TehChai Chong Teh 1131 silver badge7 bronze badges 3
  • 2 Possible duplicate of How do I return the response from an asynchronous call? – adiga Commented Mar 10, 2019 at 17:22
  • Move the for loop inside the callback. .then(data => { dog_list = data.message; const container = document.getElementById("container"); for (dog in dog_list) {....} }) – adiga Commented Mar 10, 2019 at 17:23
  • Your loop runs before the dogs are fetched.. – Mr. Alien Commented Mar 10, 2019 at 17:24
Add a ment  | 

3 Answers 3

Reset to default 5

Just construct you li inside the callback where you create dog_list...

Something like this...

let dog_list = [];
const container = document.getElementById("container");
fetch('https://dog.ceo/api/breeds/list/all')
    .then(response => {
        if (response.ok) {
            return response.json();
        } else {
            throw new Error(response.statusText);
        }
    })
    .then(data => {
        dog_list = data.message;
        for (dog in dog_list) {
            let li = document.createElement("li");
            let node = document.createTextNode(dog);
            li.appendChild(node);
            container.appendChild(li);
        }
    });

Why do you need to construct resulting DOM structure inside promise handler?

Because the plete fetch(/*...*/).then(/*...*/).then(/*...*) block will be executed asynchronously

Without waiting for that code to plete, mainline ('global') code will continue its execution from the line after that, which in your case is getting the container and start adding li elements. Problem is that at this point the processing of the response from the fetch call will not even start (even if the fetch has been executed and results have been returned) and consequently dog_list will be empty.

Since the callback in .then is asynchronous, you can populate the list inside the .then callback otherwise dog_list will still be an empty array the time when the loop runs:

fetch('https://dog.ceo/api/breeds/list/all')
  .then(response => {
    if (response.ok) {
      return response.json();
    } else {
      throw new Error(response.statusText);
    }
  })
  .then(data => populate(data.message));
function populate(dog_list){
    const container = document.getElementById("container");
    for (dog in dog_list) {
      let li = document.createElement("li");
      let node = document.createTextNode(dog);
      li.appendChild(node);
      container.appendChild(li);
    }
}
<!DOCTYPE html>
<html lang="en">

<head>
  <title>Dog Breed List</title>
</head>

<body>
  <ul id="container"></ul>
</body>

</html>

You could also try the same with async and await. Please have a look below.

const url = 'https://dog.ceo/api/breeds/list/all';

async function Main() {
  const dog_data = await getDogData(url).catch(catchError);
  const dog_list = dog_data.message;
  const container = document.getElementById("container");
  for (dog in dog_list) {
    const node = createHTMLElement('li', dog);
    container.appendChild(node);
  }
}

function catchError(err) {
  console.log('Error ', err);
}

function createHTMLElement(_node, data) {
  let li = document.createElement("li");
  li.textContent = dog;
  return li;
}

async function getDogData(_url) {
  const response = await fetch(_url);
  return await response.json();
}

Main();
<!DOCTYPE html>
<html lang="en">

<head>
  <title>Dog Breed List</title>
</head>

<body>
  <ul id="container"></ul>

</body>

</html>

发布评论

评论列表(0)

  1. 暂无评论