Handling an error inside of a promise

Handling an error inside of a promise

Fetch is a promise. normal try catch wont work with that because fetch wont instantly throw an error or resolve and by the time it does we will be out of try block that's how asynchronous functions work. We could use try catch if we convert the promise to async await .

But keep in mind that fetchMeals is an async function, and therefore, it always returns a promise. Now, if we throw an error instead of a promise, that error will cause that promise to reject.

So we can't use try-catch to wrap it unless we also await this for which we would need to turn our Effect function here into an async function, which we're not allowed to do.

Now, we could still work around that by putting that into a separate function, which we call thereafter so that we have separate functions, one for sending the HTTP request and one for error handling. And that be absolutely fine. But here, I think it's a bit easier to simply use the fact that it's a promise and add to catch method on it. Since that returns a promise, you can add then to handle success cases when the promise fulfills successfully. And we can add catch to handle errors coming up inside of the promise. And therefore, instead of try-catch here, we wanna catch the error we're getting and move that code here into this catch block. And that's the traditional promise only way of handling an error inside of a promise.

Good Meth

import classes from './AvailableMeals.module.css'
import Card from '../UI/Card';
import MealItem from './MealItem/MealItem';
import React, { useEffect, useState } from 'react'


const AvailableMeals = () => {
    const [httpError, setHttpError] = useState();



    useEffect(() => {
        const fetchMeals = async () => {
            const response = await fetch("https://reactfooddata-default-rtdb.firebaseio.com/meals.json");


            console.log("here");

            if (!response.ok) {
                //this is a constructor
                throw new Error('Something went wrong!')
            }

            const responseData = await response.json();
            if (responseData === null) {
                throw new Error('Check your URL');
            }
            const loadedMeals = [];
            for (const key in responseData) {
                loadedMeals.push({
                    id: key,
                    name: responseData[key].name,
                    description: responseData[key].description,
                    price: responseData[key].price
                });
            }

            setMeals(loadedMeals);
            setIsLoading(false);
        };


//BEST METHOD hereeeeeeeeeeeeeeeeeeeeeeeeeeeeeee
        fetchMeals().catch((error) => {
            setHttpError(error.message);
        });


    }, [])






    if (httpError) {
        return <section className={classes.MealsError}>
            <p>{httpError}</p>
        </section>
    }




    return <section className={classes.meals}>
        <Card>
            <ul>
                {mealsList}
            </ul>
        </Card>
    </section>
}

export default AvailableMeals;

Bad Meth:

import classes from './AvailableMeals.module.css'
import Card from '../UI/Card';
import MealItem from './MealItem/MealItem';
import React, { useEffect, useState } from 'react'


const AvailableMeals = () => {
    const [httpError, setHttpError] = useState();



    useEffect(() => {
        const fetchMeals = async () => {
            const response = await fetch("https://reactfooddata-default-rtdb.firebaseio.com/meals.json");


            console.log("here");

            if (!response.ok) {
                //this is a constructor
                throw new Error('Something went wrong!')
            }

            const responseData = await response.json();
            if (responseData === null) {
                throw new Error('Check your URL');
            }
            const loadedMeals = [];
            for (const key in responseData) {
                loadedMeals.push({
                    id: key,
                    name: responseData[key].name,
                    description: responseData[key].description,
                    price: responseData[key].price
                });
            }

            setMeals(loadedMeals);
            setIsLoading(false);
        };


//BAD METHOD hereeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee
try{
        fetchMeals();
}catch(error){
            setHttpError(error.message);
}
        });


    }, [])






    if (httpError) {
        return <section className={classes.MealsError}>
            <p>{httpError}</p>
        </section>
    }




    return <section className={classes.meals}>
        <Card>
            <ul>
                {mealsList}
            </ul>
        </Card>
    </section>
}

export default AvailableMeals;