Using the result from an API in a constructor

I am trying to apply my knowledge of working with APIs by making a roleplaying game character generator for my friend. In fact, it is nearly finished, but I now want to add names to the characters using a random person generator API.

I know that my code to call up the API is working:

async function getRandomName () {
  try {
    const response = await fetch (randomNameUrl);
    if (response.ok) {
      const jsonResponse = await response.json();
      console.log(jsonResponse);
      const firstName = jsonResponse.results[0].name.first;
      const lastName = jsonResponse.results[0].name.last;
      const fullName = `${firstName} ${lastName}`;
      return fullName;
    }
  }
  catch(error) {
    console.log(error);
  }
}

As I can run:

getRandomName().then(x => {console.log (x);}) 

And I can see a random name generated each time.

I got the above by searching on StackExchange, and I have also searched for a solution to my problem below on Stack Exchange, but have not found a satisfactory answer that I can understand.

So my issue is using the return value (not the Promise, but the string I return) in a constructor for the characters.

The closest I have got is:

class ZeroLevelHero {
  constructor() { 
    this.name = getRandomName().then(value => value);
... }

This means that the value of .name for each object generated with the constructor is “Promise”, and if I look in the Developer Tools I can see the contents of the Promise:

[[Prototype]]: 
Promise
[[PromiseState]]
: "fulfilled"
[[PromiseResult]]
: "Orinder Nayak"

What I want is for the .name attribute to have a value of “Orinder Nayak” in this case.

So near and yet so far… Can anyone help?

Class and constructors… don’t do anything in a constructor beyond setting up initial state. If the values needed for that state are async or rely on other function calls, that shouldn’t be the class’ problem.

I’d do something like:

class ZeroLevelHero {
    constructor(name) { this.name = name; }
}

const getRandomName = () =>
    fetch("https://api.namefake.com/") // found this one, it's neat
        .then(res => res.json())
        .then(x => x.name);


// use an async function to deal with async calls
async function createZeroLevelHero() {
    // load up the initial state data
    const name = await getRandomName();
    // return our instance with the results of our expensive calls
    return new ZeroLevelHero(name);
}

async function main() {
    const hero = await createZeroLevelHero();
    console.log(hero);
}

main().then(() => console.log("done"));
1 Like

Great, thanks for replying, and thanks for the general advice about classes, as well as a solution to my specific issue.

I saw api.namefake.com when I was looking, but forgot to say that I had defined randomNameUrl thusly:

const randomNameUrl = "https://randomuser.me/api/"

I’ll try out your approach, and hopefully it will solve my issue. It sounds like I should also refactor my code to take various other function calls out of the constructor, for the sake of cleaner code.

Adapting your advice to my project, I have now got it working with getting names from the API and displaying them on the character sheets as desired, thank you!

1 Like

Excellent. Thanks for the feedback.

1 Like