bizboz1981 / ms2_pokemon_memory_match

Milestone Project 2 - Pokemon Memory Match
0 stars 0 forks source link

Try...catch block not working as intended #1

Closed bizboz1981 closed 5 months ago

bizboz1981 commented 5 months ago

const loadPokemon = async (numberOfPairs) => { try { const randIds = new Set(); while (randIds.size < numberOfPairs) { randIds.add(randNum()); } const pokePromises = [...randIds].map((id) => fetch(pokeBaseURL + id)); const results = await Promise.all(pokePromises); for (let result of results) { if (!result.ok) { throw new Error("Pokemon failed with error"); } } return await Promise.all(results.map((res) => res.json())); } catch { return backupPokemon.slice(0, numberOfPairs); } };

I now seem to have successfully wrapped this loadPokemon function in a try...catch block. I did this so that if the api failed for some reason, then there was a backup source to create the pokemon cards. However when I 'broke' the api link (i.e. changed the pokeBaseURL value to some nonsense), so that it returned, say a 404 code, then the catch block wasn't getting triggered. I did some digging and discovered that a 404 code doesn't necessarily mean an error (in terms of the try block) so the catch block wasn't getting invoked. I found out on stack overflow how to force the try block to throw an error if the code is not in the 200s (i.e. !result.ok), and I can now get the catch block to trigger the backup pokemon. So my initial issue about why the catch block is not getting triggered, I think I've solved.

However, it only works when I store backupPokemon as an array of objects. I don't really want to have that taking up 250 lines of code, so would prefer to require it in from a json file. But this isn't working and I can't figure out why! The closest I can get is that 'require' is something to do with node.js and doesn't work as predicted on frontend files.

georgecrawford commented 5 months ago

Quick tip: triple backticks (```) can be used to paste formatted code:

const loadPokemon = async (numberOfPairs) => {
    try {
        const randIds = new Set(); // Sets cannot contain duplicate values, so will be guarantee unique pokemon
        while (randIds.size < numberOfPairs) {
            // Not 'numPairs + 1' - we want this loop to exit when length = numPairs, not run again as then we'd have 1 too many
            randIds.add(randNum());
        }
        const pokePromises = [...randIds].map((id) => fetch(pokeBaseURL + id)); // Spread the randIds set into an array which supports .map. For each id in the array, fetch a promise from the base URL with random id appended. Returns an array of promises
        const results = await Promise.all(pokePromises); // returns a single promise that resolves when all pokePromises have resolved; returns an array
        for (let result of results) {
            if (!result.ok) {
                throw new Error("Pokemon failed with error");
            }
        }
        return await Promise.all(results.map((res) => res.json()));
    } catch {
        return backupPokemon.slice(0, numberOfPairs);
    }
};

And if you want syntax highlighting, you can put js after the opening triple backticks like this:

const loadPokemon = async (numberOfPairs) => {
    try {
        const randIds = new Set(); // Sets cannot contain duplicate values, so will be guarantee unique pokemon
        while (randIds.size < numberOfPairs) {
            // Not 'numPairs + 1' - we want this loop to exit when length = numPairs, not run again as then we'd have 1 too many
            randIds.add(randNum());
        }
        const pokePromises = [...randIds].map((id) => fetch(pokeBaseURL + id)); // Spread the randIds set into an array which supports .map. For each id in the array, fetch a promise from the base URL with random id appended. Returns an array of promises
        const results = await Promise.all(pokePromises); // returns a single promise that resolves when all pokePromises have resolved; returns an array
        for (let result of results) {
            if (!result.ok) {
                throw new Error("Pokemon failed with error");
            }
        }
        return await Promise.all(results.map((res) => res.json()));
    } catch {
        return backupPokemon.slice(0, numberOfPairs);
    }
};

Use single backticks for unformatted code snippets.

georgecrawford commented 5 months ago

Glad you've found the answer yourself. if (!result.ok) is the way to generally catch any network errors (wrong type of response code, timeouts, DNS issues, etc.), and you should always use it after trying to read the response of a fetch() call.

bizboz1981 commented 5 months ago

project finishes