Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

139
Views
Handling of async data in JS class

Goal: I want to build a class that addresses a news interface and renders the data in the view. My class (MyNews) has several methods and one method is fetchNews(). In this method I get the data from the API. The data from the api should be assigned in a class varaible (news). In another method (showNews()) I want to access the data to iterate over it.

My problem: I am beginner in js and I wonder how to query the data. From my understanding the flow is like this: constructor calls fetchNews fetch news first gets a promise and waits until the promise is resolved then the data is assigned to the member but the JS async is running js doesn't wait at this point until the promise is resolved and it continues working with the empty array. This is exactly my problem.

Question What do I need to do or change to fetch the data correctly. So that I can build a HTML list for example.

My JS Code

class MyNews {
  news = [];
  
  apiUrl = "https://jsonplaceholder.typicode.com/posts";
  
  constructor() {
    this.news;
    this.fetchNews();
  }
  
  fetchNews() {
    fetch(this.apiUrl)
      .then(async (data) => {
        this.news = await data.json(); 
        console.log("A:",this.news.length); // i have results
      })
      .catch((err) => {
        console.log(err)
      });
                // ...
  }
  
  showNews() {
    console.log("B:",this.news.length); // empty array
    
    return this.news;
  }
}
    

n = new MyNews;
console.log("C:", n.showNews().length );

about 4 years ago · Juan Pablo Isaza
3 answers
Answer question

0

I'd suggest adding a getAndShowNews() function to your class.

We'll then ensure to return the promise from the fetchNews() fetch call, so we can await it in another async function.

In the getAndShowNews() function we'll await the fetchNews() result (a promise), this will ensure the news items are populated. We'll then show the news by looping through each item.

You could do this in a function outside of the class, but it seems to make sense to do it in the class.

class MyNews {
  news = [];
  
  apiUrl = "https://jsonplaceholder.typicode.com/posts";
  
  constructor() {
    this.fetchNews();
  }
  
  fetchNews() {
    return fetch(this.apiUrl)
      .then(async (data) => {
        this.news = await data.json(); 
      })
      .catch((err) => {
        console.log(err)
      });        // ...
  }
  
  showNews(newsElementId, count = 8) {
    let newsElement = document.getElementById(newsElementId);
    for(let newsItem of this.news.slice(0,count)) {
      let el = document.createElement('li');
      el.innerText = newsItem.title;
      newsElement.appendChild(el);
    }
  }

  async getAndShowNews(newsElementId) {
    // Wait for the fetchNews() call to complete...
    await this.fetchNews();
    // Show the news...
    this.showNews(newsElementId);
  }
}
    
n = new MyNews();
n.getAndShowNews('news');
<b>News</b>
<ol id='news'>
</ol>

about 4 years ago · Juan Pablo Isaza Report

0

The problem is that fetch() is an async function. This is what actually happens:

  1. Constructor is called
  2. fetchNews is started
  3. Constructor probably finishes before fetchNews
  4. showNews probably runs before fetchNews is done

First thing that comes to mind is using the await keyword or using promises directly. This does not fully solve your problem though, because constructor can not be an async function.

I recommend this solution:

Move the call of fetchNews to an init method on the MyNews class and make it async.

class MyNews {
    ...
    async fetchNews() {
        await fetch(...);
    }
    ...
    async init() {
        await fetchNews();
    }
    ...
}
const news = new MyNews();
await news.init();
news.showNews();

You can find more on async constructors in this stackoverflow thread.

btw: the this.news; in the constructor seems unnecessary.

about 4 years ago · Juan Pablo Isaza Report

0

A couple of issues:

  1. The first is that fetchNews is an async process. In your example showNews will always be 0 because fetchNews hasn't fetched anything when showNews is called. We can mitigate some of this by moving the calling of those methods outside of the class.

  2. You have an odd mix of fetch and async/await - it's best to stick with one or the other.

class MyNews {

  apiUrl = 'https://jsonplaceholder.typicode.com/posts';

  // `async/await` function - fetches the JSON, and
  // sets the `news` field to the parsed JSON
  async fetchNews() {
    try {
      const response = await fetch(this.apiUrl);
      if (response.ok) this.news = await response.json();
    } catch (err) {
      this.error = err.message;
    }
  }
  
  formatNews() {
    return this.news.map(n => {
      return `<p>${n.title}</p>`;
    }).join('');
  }
  
  // Return the news or the error if there was one.
  showNews() {
    if (!Array.isArray(this.news)) return this.error;
    return this.formatNews();
  }

}

// Piecing it together we create a new
// object, call and `await` `fetchNews` and
// then call `showNews`
async function main() {
  const myNews = new MyNews();
  await myNews.fetchNews();
  document.body.innerHTML = myNews.showNews();
}


main();
p { border: 1px solid #787878; padding: 0.3em; border-radius: 5px; margin: 0.2em; text-transform: capitalize; }
p:hover { cursor: pointer; background-color: #ffffd0; }

about 4 years ago · Juan Pablo Isaza Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!