ETHan
ETHan

Reputation: 207

Using async await on promise in svelte (#await) is not returning the desired data that is formatted in a later function call

I am currently working with a API that does not return JSON. To get around this, I take the response and push it to a array (while formatting it to remove any indentation and split each number in the response). I then use this array of 183 numbers and run a for loop against an array with 183 characters to generate an object (with custom key value pairs) from the response.

Where things get confusing is when I start to use the data in my HTML. Usually you can just say <p>{data.overallRank}</p> but I am getting the error that the object is undefined. This makes sense because the data = {} was not created until the function ran.

After searching for a solution, I cam across svelte await blocks. You can read on them here and look at the tutorial: https://svelte.dev/tutorial/await-blocks

After trying to implement this feature, I have the following code:

let playerStats = []
    let proxy = "https://cors-anywhere.herokuapp.com/"
    let url =  proxy + "https://secure.runescape.com/m=hiscore_oldschool/index_lite.ws?player=Hess"
    const data = {};
    
    let promise = getPlayer();
    async function getPlayer() {
        return await fetch(url).then((response) => response.text())
            .then((data) => {
                return data;
            });
        }

getPlayer().then((playerData) => {
// format data
  playerStats.push(playerData.replace(/\n/ig, ",").split(','));
  console.log(playerStats);

// Begin object generation
// names array shortened
let names = ["overallRank", "overallLvl", "overallXP", "attRank", ]
  
const data = {};
    for (var i = 0; i < playerStats[0].length; i++) {
        data[names[i]] = playerStats[0][i];
    }
console.log(data);
});
<main>

{#await promise}
    <p>Search for a Player...</p>
{:then data}
    <p>The data is {data}</p>
{/await}

</main>

The issue with this code is that it is printing out the data from the return data, which returns the unformatted data and not the object.

I want to return the object that is created after the second function getplayer().then()... so I can use that object throughout my HTML.

I hope I explained things well and thank you in advance for any help.

Upvotes: 1

Views: 8636

Answers (2)

Thomas Hennes
Thomas Hennes

Reputation: 9939

You were actually very close to sorting it out, just a bit of confusion regarding how promises work I believe.

All you need to do is format your data within the block where the data is handled following the fetch & decode operations:

  async function getPlayer() {
    return await fetch(url)
      .then((response) => response.text())
      .then((data) => {
        return formatData(data);
      });
  }

Your formatData() function is essentially there already, you just need minor changes in your code:

  function formatData(playerData) {
    playerStats.push(playerData.replace(/\n/ig, ",").split(','));
    console.log(playerStats);

    // Begin object generation
    // names array shortened
    let names = ["overallRank", "overallLvl", "overallXP", "attRank", ]
  
    const data = {};
    for (var i = 0; i < playerStats[0].length; i++) {
      data[names[i]] = playerStats[0][i];
    }
    console.log(data);
    return data;
  }

Finally, you do not need to explicitly declare a promise to use it in an {#await} block, you know getPlayer() returns a promise, so you can directly use that instead:

<main>
{#await getPlayer()}
    <p>Search for a Player...</p>
{:then data}
    <p>Overall Rank: {data.overallRank}</p>
{/await}
</main>

See functioning REPL

Upvotes: 3

Stephane Vanraes
Stephane Vanraes

Reputation: 16411

It is returning the formatted data because that what is returned by the promise function. In order to get the formatted data, you have to add the formatting to the chain of promise

async function getPlayer() {
  return await fetch(url)
    .then((response) => response.text())
    .then((playerData) => {
       // here your transformation
       // do not forget to actually return something
       return data;
    });

Upvotes: 5

Related Questions