I am working on an NBA statistics app. I have many routes and database queries split into a couple different files and am unsure about how to handle errors. Here is the script-side function that calls my 'boxScoresTraditional/home/:playerid/:season' route in the 'mutualScript.js' file:
FULL GITHUB REPOSITORY: https://www.github.com/JackPetersenCode/NBA
mutualScript.js:
const getSeasonStatAvgLocal = async(stat, year, playerId, H_or_V) => {
let url;
if (H_or_V === 'home') {
url = '/boxScoresTraditional/home/' playerId '/' year;
} else {
url = '/boxScoresTraditional/visitor/' playerId '/' year;
}
let gameDetailsArray = await getJsonResponse(url);
let statTotal = await getSeasonTotalOfStat(stat.toLowerCase(), gameDetailsArray);
//let gamesPlayed = await getGamesPlayedInSeason(gameDetailsArray);
let gamesPlayed = gameDetailsArray.length;
let statAverage = statTotal / gamesPlayed;
return Number.parseFloat(statAverage).toFixed(2);
}
In this line above:
let gameDetailsArray = await getJsonResponse(url);
the 'boxScoresTraditional/home/:playerid/:season' url is sent to the 'getJsonResponse' function in the same file. The getJsonResponse function makes a fetch call to the route, which is in another file called 'boxScoresTradtionalRoutes.js'. Here are both files, first the getJsonResponse function then the boxScoresTraditionalRoutes.js:
mutualScript.js:
const getJsonResponse = async (url) => {
console.log(url);
const response = await fetch(url);
try{
if (response.ok){
const jsonResponse = await response.json();
return jsonResponse;
}
} catch(err){
console.log(err);
}
}
boxScoresTraditionalRoutes.js:
const express = require('express');
const router = express.Router();
const boxScoreTraditional = require('../services/boxscorestraditionalQueries')
/**
* @swagger
* /boxScoresTraditional/home/{playerid}/{season}:
* get:
* parameters:
* - in: path
* name: playerid
* schema:
* type: string
* required: true
* description: String ID of the player who's box scores we are getting
* - in: path
* name: season
* schema:
* type: string
* required: true
* description: String season of the box scores we are getting
* responses:
* '200':
* description: A successful response
*
*/
router.get('/home/:playerid/:season', boxScoreTraditional.getBoxScoreTraditionalHome);
router.get('/visitor/:playerid/:season', boxScoreTraditional.getBoxScoreTraditionalVisitor);
The route then calls the database query in the file 'boxScoresTraditionalQueries.js' shown below:
const getBoxScoreTraditionalHome = (request, response) => {
const {playerid, season} = request.params;
let newSeason = JSON.stringify(season);
let stringSeason = newSeason.replace(/"/g, '');
db.query(`SELECT * FROM "boxscorestraditional${stringSeason}"
INNER JOIN "boxscoresummary${stringSeason}"
ON "boxscorestraditional${stringSeason}".game_id = "boxscoresummary${stringSeason}".game_id
WHERE player_id = $1
AND "boxscoresummary${stringSeason}".home_team_id = "boxscorestraditional${stringSeason}".team_id
ORDER BY "boxscorestraditional${stringSeason}".id`, [playerid], (error, results) => {
if (error) {
throw error
}
response.status(200).json(results.rows)
})
}
Here is my issue: If I make a bad call to the getBoxScoreTraditionalHome function above, the app crashes and the error never gets back up script-side to the catch block in 'getJsonResponse'. Testing the route with Postman just crashes my app as well, as I am just throwing an error every time. I would ideally want to put a more extensive custom error Handler in the catch block of the 'getJsonResponse' function, as every single get request goes throw that function and I could handle everything there in one place, as opposed to after every sql query in my 'boxScoresTraditionalQueries.js' file. Do I just remove the 'if(error){ throw error }' from my backend and just stick with 'response.status(200).json(results.rows)' and let the catch block in the 'getJsonResponse' function catch all errors?
Thank you in advance for your time, I know it's very valuable and this Node.js noobie appreciates it very much
Jack
I tried res.sending the error back from the backend, I've had it print out the error message to postman, but I would much rather send that error back up to the 'getJsonResponse' in the front end so I can catch all the different errors in that one catch block.
After reading some of the recommended questions, it looks like error checking on the server end is paramount. My new evolved question after some reading, how would I exactly call an error handler middleware from the boxScoresTraditionalQueries.js file? Here is the code one more time from the database query, in the if(error){ throw error } block, how would I call an error handler middleware?
const getBoxScoreTraditionalHome = (request, response) => {
const {playerid, season} = request.params;
let newSeason = JSON.stringify(season);
let stringSeason = newSeason.replace(/"/g, '');
db.query(`SELECT * FROM "boxscorestraditional${stringSeason}"
INNER JOIN "boxscoresummary${stringSeason}"
ON "boxscorestraditional${stringSeason}".game_id = "boxscoresummary${stringSeason}".game_id
WHERE player_id = $1
AND "boxscoresummary${stringSeason}".home_team_id = "boxscorestraditional${stringSeason}".team_id
ORDER BY "boxscorestraditional${stringSeason}".id`, [playerid], (error, results) => {
if (error) {
throw error
}
response.status(200).json(results.rows)
})
}
Sorry if I'm being redundant. This program got way too big too fast and I am, with shame, going back to document/errorhandle/test everything. I just want to get one route perfect, so I have a template to crank out the rest of the routes.
Thanks, Jack
CodePudding user response:
There are many ways to go about error handling. If your using Express and a templating engine (pug, hbs etc..), one way I found to work quite well is using response.render()
.
For example, inside of your if
try the following code:
return response.render("path/to/view", {
message: "Page Error!",
});
This will render a view of your choice when an error occurs, I do the same view as the request is coming from, but this time you're also sending the message
variable to the HTML template as well. This variable should contain some sort of error message.
Then in your view, you can check for the variable. This is an example using hbs:
{{#if message}}
<div >
{{message}}
</div>
{{/if}}