0

I am having troubles accessing a object, I tried to define a let and write a new object to it, however when I try to access it, is not possible, this is what my attempt looks like:

function Player(uniqueId, name, figureString, motto, memberSince) {
    this.uniqueId = uniqueId;
    this.name = name;
    this.figureString = figureString;
    this.motto = motto;
    this.memberSince = memberSince;
}

...

let player;
getUser
    .then((res) => {
        player = new Player(res.uniqueId, res.name, res.figureString, res.motto, res.memberSince);
    })
    .catch(() => {
            ...
    });

        // Trying to access player here
console.log(player.name + player.figureString);
Tom
  • 445
  • 1
  • 4
  • 10
Mesa
  • 3
  • 4
  • so whats the error you are getting – Learner Aug 30 '18 at 11:35
  • are you sure attributes in `res` are populated? console.log(res) – SubSul Aug 30 '18 at 11:37
  • when you declare let player it has the window scope, so i hope its accessible from anywhere. i hope get user is an ajax call , may be you are running the console.log(player.name + player.figureString); before the value gets from server – Learner Aug 30 '18 at 11:39
  • The error Im getting is: `Cannot read property 'name' of undefined` and yes, res is populated – Mesa Aug 30 '18 at 11:39

3 Answers3

0

You are attempting to call console.log after an asynchronous function call to getUser. It's likely that player is still undefined as getUser has not resolved (at this point in time) to set player = new Player(...). If you adjust your code to follow the asynchronous flow and log in then after you've re-assigned your player variable, you should be able to access it.

Peak
  • 349
  • 2
  • 6
  • Basically I only need the `res.uniqueId` to make a request to another api, is it good practice to create the new request inside the `.then((res) => {` or should I try to make the uniqueId accessible from anywhere and create a new function for the get request? – Mesa Aug 30 '18 at 11:42
  • If you need to make a request off another request, then yes, you can chain promises. You can split the functions up so you have a Promise for getUser and a Promise for the next request if you don't want to nest too much. If you need the value later down the line then you can store it somewhere (e.g. a global object or a bit of state somewhere) and you can access it from there. – Peak Aug 30 '18 at 11:49
0

when you declare let player it has the window scope, so i hope its accessible from anywhere. i hope get user is an ajax call , may be you are running the console.log(player.name + player.figureString); before the value gets from server . So you can do in the below way , you can use the console.log(player.name + player.figureString); inside the then function as shown below.

function Player(uniqueId, name, figureString, motto, memberSince) {
    this.uniqueId = uniqueId;
    this.name = name;
    this.figureString = figureString;
    this.motto = motto;
    this.memberSince = memberSince;
}

...

let player;
getUser
    .then((res) => {
        player = new Player(res.uniqueId, res.name, res.figureString, res.motto, res.memberSince);
        // once res is populated
console.log(player.name + player.figureString);
    })
    .catch(() => {
            ...
    });

        // Trying to acces player here 
console.log(player.name + player.figureString);
Learner
  • 8,379
  • 7
  • 44
  • 82
  • 1
    While this code snippet may solve the problem, it doesn't explain why or how it answers the question. Please [include an explanation for your code](//meta.stackexchange.com/q/114762/269535), as that really helps to improve the quality of your post. Remember that you are answering the question for readers in the future, and those people might not know the reasons for your code suggestion. – Luca Kiebel Sep 13 '18 at 17:08
0

Like other people said the problem is with console.log(...) and asynchronous code. So player is not defined when console.log() is invoked. To avoid this, You can use async/await.

function Player(id, name) {
  this.name = name;
  this.id = id;
}

const getUser = () => {
  return new Promise((resolve, reject) => {
    return resolve({ name: "Karl", id: 1 });
  });
}

(async () => {
  try {
    const { name, id } = await getUser();
    const player = new Player(id, name);
    console.log(`id: ${player.id}, name: ${player.name}`);
  } catch (err) {
    //handle error
  }
})();

Not that I added getUser stub and simplified example to use only name and id. At the end You can see IIFE because to use await keyword, it has to placed inside async function. That way You can be sure that player is defined.

KarlR
  • 1,545
  • 12
  • 28