0

So im very new to fullstack and been working on a little vanilla js project to make a website that calls a server I run that calls chess.com api, for example retrieving all elo ratings is:

https://api.chess.com/pub/player/${username}/stats

So I made a backend call in node-js:

const fetch = require('node-fetch');

exports.getChessManStats = () => {
   return (req, res) => {
    res.set('Access-Control-Allow-Origin', '*');
    const username = req.param('username');
    console.log(req.param('username'));
    fetch(`https://api.chess.com/pub/player/${username}/stats`)
    .then(res2 => res2.json() )
    .then(chessManData => {
        res.json({  
            daily: chessManData.chess_daily.last.rating,
            rapid: chessManData.chess_rapid.last.rating,
            blitz: chessManData.chess_blitz.last.rating,
            bullet: chessManData.chess_bullet.last.rating,
        })
    })
    .catch(err => console.log(err));
   } 
};

the code then runs with express on the main.js with:

const app = express();
app.get('/getRating',chessManController.getChessManStats()); 

obviously later down the line I called app.listen(3000) .

So then at the frontend I made a button that calls this function :

const makeUserStats = () => {
const username = document.getElementById('username').value;//id=username is type input
document.getElementById('rating').innerHTML = `Searching`; //making the rating div into 'searching'
console.log(`http://localhost:3000/getRating?username=${username}`)//just seeing the sting I send
fetch(`http://localhost:3000/getRating?username=${username}`)
.then(rating => {
    document.getElementsByClassName('statButton').disabled = true;//disabling buttons until the data arrives
    console.log('got json');
    return rating.json();
})
.catch(err => console.log(err))//looking for errors
.then((userRating => {
    window.userRating = userRating;//saving the stats globaly to use in other buttons
    window.user = username;
}))
.then(() => {
    document.getElementsByClassName('statButton').disabled = false;//enabling the buttons again
    document.getElementById('rating').innerHTML = `${window.user} rating is:`; 
})
}

and now when I press the button it works with some usernames and with some dont. YoniRamot (mine) works, hikaru (pro player) works, atomicstew (friend) doesnt work, idobl (friend) doesnt work. and the wierd part is it does'nt catch any errors, just waiting for answer that it never gets. but if you go the the api they all exist:

https://api.chess.com/pub/player/yoniramot/stats -- mine

https://api.chess.com/pub/player/hikaru/stats --proplayer

https://api.chess.com/pub/player/atomicstew/stats --friend

https://api.chess.com/pub/player/idobl/stats --friend

the console of the backend shows:

atomicstew
TypeError: Cannot read property 'last' of undefined
    at C:\Users\Yonatan\Desktop\coding\training\intermediateChess\backend\controllers\chessStats.js:12:45
    at processTicksAndRejections (internal/process/task_queues.js:93:5)

meaning that the backend gets the username but does'nt find it in the api for some reason.

please help my mind is blowing at this point.

-edit 1-

So I added a console log before sending the res with the data, and it printed:

atomicstew
{
  chess_rapid: {
    last: { rating: 1228, date: 1612114999, rd: 28 },
    best: {
      rating: 1265,
      date: 1611786478,
      game: 'https://www.chess.com/live/game/6380128206'
    },
    record: { win: 233, loss: 202, draw: 19 }
  },
  chess_blitz: {
    last: { rating: 902, date: 1611928398, rd: 50 },
    best: {
      rating: 1010,
      date: 1609882454,
      game: 'https://www.chess.com/live/game/6297568401'
    },
    record: { win: 26, loss: 24, draw: 4 }
  },
  fide: 0,
  tactics: {
    highest: { rating: 1659, date: 1609635730 },
    lowest: { rating: 387, date: 1608148134 }
  },
  lessons: {},
  puzzle_rush: {}
}
TypeError: Cannot read property 'last' of undefined
    at C:\Users\Yonatan\Desktop\coding\training\intermediateChess\backend\controllers\chessStats.js:13:45
    at processTicksAndRejections (internal/process/task_queues.js:93:5)

and the references I am calling are right there, so I am still stuck.

-edit 2-

I noe realized that if a player didnt play a certain game mode than the api doesnt hold that values. any ideas how to save the data as 0 or null if there is no data neatly?

  • What the error means is one of the property (`chess_rapid`, `chess_daily`, `chess_blitz`, `chess_bullet`) in `chessManData` undefined. Maybe check `chessManData` to see if the required properties actually exist? – Sagar Chilukuri Feb 01 '21 at 08:36
  • @SagarChilukuri I added an update, can you help any further? – Yonatan Ramot Feb 01 '21 at 08:55
  • In the above response, `chess_daily` & `chess_bullet ` properties are missing. So, the above error is correct. You can modify your code to read the properties optionally .i.e, modify the lines to ` daily: chessManData.chess_daily.last.rating || {},`. Hope this helps. – Sagar Chilukuri Feb 01 '21 at 08:58
  • @SagarChilukuri the problem was solved by the answer below, but thatnks for helping me pointing at the problem! – Yonatan Ramot Feb 01 '21 at 09:06

1 Answers1

0

Issue is in following block of code where you are trying to access last field on different properties in response:

res.json({  
      daily: chessManData.chess_daily.last.rating,
      rapid: chessManData.chess_rapid.last.rating,
      blitz: chessManData.chess_blitz.last.rating,
      bullet: chessManData.chess_bullet.last.rating,
})

I had quick look at response for following API and it does not have chess_daily and chess_bullet properties.

https://api.chess.com/pub/player/atomicstew/stats

Since you are trying to access chessManData.chess_daily.last.rating and chess_daily is not present in chessManData, you are getting exception for .last.

In order to fix it, you can replace above block by following:

res.json({  
     daily: chessManData.chess_daily && chessManData.chess_daily.last ? chessManData.chess_daily.last.rating : null, // replace null with appropriate default value for rating
     rapid: chessManData.chess_rapid && chessManData.chess_rapid.last ? chessManData.chess_rapid.last.rating : null,
     blitz: chessManData.chess_blitz && chessManData.chess_blitz.last ? chessManData.chess_blitz.last.rating : null,
     bullet: chessManData.chess_bullet && chessManData.chess_bullet.last ? chessManData.chess_bullet.last.rating : null,
})

Raeesaa
  • 3,267
  • 2
  • 22
  • 44
  • is there any documentation of that syntax I could read? – Yonatan Ramot Feb 01 '21 at 09:05
  • @YonatanRamot I have just checked if object - chess_daily, chess_rapid, etc. in this case - is defined / present in response and used ternary operator to conditionally set value. This is a very common use-case we come across while working with objects in javascript. Following stack overflow post might help in getting better understanding of undefined objects - https://stackoverflow.com/a/12589152/2235057. – Raeesaa Feb 01 '21 at 10:11