Question about my code

I am having trouble understanding what’s preventing my code from running. Previously the searchEm function was working fine, it displayed the URL with an appended “input” at end. I started working on the displayEm function and somewhere along the line everything ceased to function.

Just trying to clear somethings up before I get ahead of myself here. Can you not call a function from within a function the way I’m trying to do here?


const searchBtn = document.getElementById("search-button")

const searchInput = document.getElementById("search-input")

let pokemon = "https://pokeapi-proxy.freecodecamp.rocks/api/pokemon/"

const catchEm = () => fetch(pokemon)
.then((res) => res.json())
//.then((pokemon) => console.log(pokemon))
.catch((alert) => alert("no!"))


//console.log(catchEm())






const searchEm = () => {
  let value = searchInput.value;
   pokemon += value;
   catchEm(); 
  // console.log(catchEm());
   return;
} 
 

 //const displayEm = () => {
 // searchEm()
  //searchInput.value = "";
 // console.log(catchEm())

// }



//catchEm()

searchBtn.addEventListener("click", searchEm) 

I think the issue is with your catchEm function. You are fetching the data, but then you aren’t doing anything with it. The first thing I would highly recommend is that you use the async/await pattern for your functions that depend on Promises. It will make the logic much clearer to follow because they follow the traditional function structure. If you aren’t familiar with this, then have a look at the MDN page for the Fetch API. There are plenty of examples in there to learn from.

1 Like

I’ve read through several articles on Async functions now but I’m still confused as to why this doesn’t execute properly. When running catchEm on it’s own it returns the expected list of mons. When running it as a subfunciton of searchEm it also runs as expected and returns the appended list of mons from the user input as per the searchEm function however, if I try to console.log(catchEm) at the end of searchEm the result is undefined. See below.

I even tried turning the searchEm function into an async function for good measure, any advice would be greatly appreciated. I must be missing something fundamental here…


const searchBtn = document.getElementById("search-button")

const searchInput = document.getElementById("search-input")

let pokemon = "https://pokeapi-proxy.freecodecamp.rocks/api/pokemon/"

async function catchEm() {  
  try {
  const monList = await fetch(pokemon);
  const chosenMon = await monList.json() ;
  //console.log(chosenMon);
   return;
   } 
  catch(alert) {
    alert("error")
  }
}

//console.log(catchEm())






async function searchEm() {
  let value = searchInput.value;
   pokemon += value;
   await catchEm();
   console.log(catchEm())  
   return;
   
  
} 
 

 const displayEm = () => {
  searchEm()
  searchInput.value = "";
  //console.log(searchEm())

 }



//catchEm()

searchBtn.addEventListener("click", displayEm) 

None of your functions are returning anything. In your catchEm function, you are going to all that work to get a json object, but then you are returning undefined. So what was the point of the fetch?

In the searchEm function, why are you calling catchEm? I’m assuming it is to get some information from it. But you aren’t saving that information off to use for later. And should searchEm return a value other than undefined that can be used in displayEm?

Do you get what I’m saying here? You are just calling functions, but you aren’t doing anything with the results.

I read you loud and clear on that, I guess it was my impression that using the return statement at the end of a function would implicitly return the value of that function. So simply calling the function from within another one would return the desired results.

At the risk of sounding like a complete idiot, because now I’ve been messing with it some more, it seems like even ending say the catchEm function with something like
“return chosenMon” isn’t enough to get the results of that function more accessible throughout the code. Should I be declaring global variables and defining them with the values of the functions for later use or am I just spiraling into a new direction now?

In general, no. You want to try to limit your use of globals. But sometimes a global is helpful, for example, to define the URL you are going to use to fetch your data, as you did with the pokemon variable. But then you modified that variable in searchEm. What happens when you call searchEm more than once?

What is the purpose of the catchEm function? You must have had some idea what you wanted the function to get for you, and that is what it should return. It could be that chosenMon is exactly what you want it to return. I don’t know for sure since it’s not my function and I don’t know exactly how you are organizing your code.

chosenMon is exactly what I would like to return from catchEm. Ending the catchEm function with “return chosenMon” would lead me to believe the next time I call catchEm(), within another function or otherwise, I would get the chosenMon value but it seems like whenever I console.log chosenMon outside that function I get undefined.

Modifying pokemon from within searchEm is intended to add the user input to the end of the webpage referenced in catchEm which, works but I am only able to verify that by console.logging from within catchEm again.

It’s as you said, I think I’m missing some fundamental syntax that isn’t allowing me to easily access the return values of these functions when I need them.

The variable chosenMon is declared inside of the catchEm function, so you can’t access that specific variable anywhere else except inside the function. But I’m not sure I’m understanding you 100%, so you might have to give a code example if I didn’t get it right. When catchEm returns chosenMon, then the calling function will need to save that return value in a variable. Then you can access the return value (which was in chosenMon) through that new variable.

Yes, it definitely does that. What I’m suggesting is that you don’t wan’t to do that. It will work exactly the way you want the first time you call searchEm, but what will happen the second time you call searchEm?

You aren’t saving off the values that these functions return so you can do something with them. Look at what you are doing in your catchEm function. You call fetch and then save off the return value of that function call in the variable monList. And then you call the json method on monList and save off the return value of that method call in chosenMon. So if you call catchEm in searchEm, then why can’t you save off the return value of catchEm the same way? And then you can use the return value to do whatever else you need to do in searchEm.

I do see the issue with searchEm adding the value of the user input to the end of the webpage. My thoughts were that it would be easy enough to reset the function at the end to avoid that being an issue but I’ll heed your warning on that. I think the way the code sits now best illustrates my greater confusion.

Cutting out the displayEm function entirely, I would think that declaring the test variable with the result of catchEm() within the searchEm function would give me the value of chosenMon.

In the searchEm function, console.log(test) returns {}. This must be where I’m not understanding. Am I not declaring the test variable in the right location? Am I not returning the value of chosenMon the right way? Am I not calling the catchEm function from within searchEm the right way? I feel I conceptually understand what needs to happen but I’m not understanding the proper execution.

const searchBtn = document.getElementById("search-button")

const searchInput = document.getElementById("search-input")

let pokemon = "https://pokeapi-proxy.freecodecamp.rocks/api/pokemon/"


async function catchEm() {  
  const monList = await fetch(pokemon);
  const chosenMon = await monList.json() ;
  //console.log(chosenMon);
  return chosenMon;
//.catch((alert) => alert("no!")) 
}





const searchEm = () => {
  let test = catchEm()
  let value = searchInput.value;
   //pokemon += value; 
   console.log(test);  
   //return searchEm;
   
  
} 
 

 const displayEm = () => {
  searchEm()
  searchInput.value = "";
  console.log(searchEm())

 }



//catchEm()

searchBtn.addEventListener("click", searchEm) 

Remember, catchEm is declared as an asynchronous function, just like fetch is an asynchronous function. What do you need to do when you call an asynchronous function in order to wait for the function to return its result?

Wow, ok, searchEm’s gotta be async as well to await the response from catchEm. After now finally getting a slight grip on these I feel like they make more sense then traditional functions. Do you find yourself using async functions more than traditional?
As you stated at the beginning of this, I feel like they make more sense from a logical standpoint, I’m not really sure why you would go back to traditional if these flow like this, it seems like it’s easier to comprehend both in code and thought process.

I appreciate all the advice and most importantly your patience. You wouldn’t believe how arcane even the simple things are when you’re teaching yourself. Sometimes all the knowledgebases in the world can’t substitute for basic question asking.

Just to be clear, async functions are what I was referring to as “traditional” functions. There is no choice between async and traditional functions. They are the same thing.

When I mentioned traditional functions above, that was in contrast to using promise chaining. For example, your code initially was:

const catchEm = () => fetch(pokemon)
.then((res) => res.json())
.catch((alert) => alert("no!"))

This is using a promise chain, calling the then and catch methods. But now you have switched to the more traditional function approach:

async function catchEm() {  
  const monList = await fetch(pokemon);
  const chosenMon = await monList.json() ;
  return chosenMon;
}

The async allows you to treat asynchronous functions as if they were synchronous so that you can use this traditional approach. In my opinion, the async method makes it much easier to organize your code and reason about what is happening with the asynchronous functions you are calling.

So the choice here is not between async and traditional, but rather between traditional and promise chaining. You only need to use async/await when you are dealing with asynchronous functions.

1 Like

This topic was automatically closed 182 days after the last reply. New replies are no longer allowed.