0

Im trying to fetch some data from an api problem is the render cards function begins to execute before the data have been saved for some reason, and when i try to render i get undefined since the cards are undefined.

when it did work it also returned the data stringified and not parsed for some reason

onInit happens on body load.

<body onload="onInit()">

function onInit() {
      FetchCards();
    renderCards();
}



function FetchCards(){
    var cards =loadFromStorage(KEY)
    if(!cards){ 
        fetch('http://www.filltext.com/?rows=10&fname=%7bfirstName%7d&lname=%7blastName%7d&tel=%7bphone|format%7d&address=%7bstreetAddress%7d&city=%7bcity%7d&state=%7busState|abbr%7d&zip=%7bzip%7d&pretty=true')
        .then(res => {
            if(res.ok) res.json()
            .then(data=>{
                console.log(data);
                saveToStorage(KEY,JSON.stringify(data))  
            })
        })     
    }
}

function renderCards() {
    var cards = getCardsForDisplay()....


function getCardsForDisplay(){
    var cards =loadFromStorage(KEY)
    return cards
}

function saveToStorage(key, val) {
    localStorage.setItem(key, JSON.stringify(val))
}

function loadFromStorage(key) {
    var val = localStorage.getItem(key)
    if(!val || val==='undefined') return undefined;

    return JSON.parse(val)
}
Kosta
  • 1
  • 1
  • simply move renderCards call to fetchcards, below saveToStorage. That's the most simple way to do it (simpler than waiting for an async function etc.) – Pierre Apr 15 '20 at 18:52
  • i want a seperation, its an MVC design pattern – Kosta Apr 15 '20 at 18:53
  • not cleared need more code. – vlad-grigoryan Apr 15 '20 at 18:54
  • You can use Promise (which you already use maybe without knowing through Fetch API and the `then` method) – Pierre Apr 15 '20 at 18:56
  • thats the entire code vlad, nothing else mate, mind showing me an example pierre? – Kosta Apr 15 '20 at 18:57
  • This example isn't a [mcve] because you don't show how you're calling these functions. Even so, it basically can't work because `FetchCards` is asynchronous and `renderCards` will run before the result of `fetch` is set. You'll need to return a promise and `await` it or chain the rendering using `.then`. Anything that isn't `await`ed or inside a `then` is guaranteed to execute first. – ggorlen Apr 15 '20 at 18:58
  • Please see [how do I return the response of an asynchronous call](https://stackoverflow.com/questions/14220321/how-do-i-return-the-response-from-an-asynchronous-call) for more information. – ggorlen Apr 15 '20 at 18:59
  • i did state that in the post, will edit to clarify – Kosta Apr 15 '20 at 19:00
  • Why not using a closure? Then the function name is never known to others. – Markus Zeller Apr 15 '20 at 19:02

2 Answers2

0

You'll have to use async/await keywords.

function onInit() {
    FetchCards().then(data => {
    // your previous logic.

    }).catch(err => console.log(err)).finally(() => {
        renderCards();
    })
}

async function FetchCards() {
    // The result is a promise
    const result = await fetch("https://example.com"); 
    return result;
}
CodeEnzyme
  • 16
  • 5
0

a solution if a newcomer like myself encounters this problem:

what i needed to do is wait for a response from the fetch, await the object to convert to json , and only then save it,

in the onInit function i simply await for it to fetch the cards,

 async function onInit() {
  await FetchCards()
   renderCards();
}

 async function FetchCards(){
    var cards =  loadFromStorage(KEY)
    if(!cards){ 
       const response = await fetch('url'); 
           const data= await response.json()
            saveToStorage(KEY,data)     
       return data
    }
return cards
 }
Kosta
  • 1
  • 1