FAQ: Requests with Fetch API - Making an async GET Request

This community-built FAQ covers the “Making an async GET Request” exercise from the lesson “Requests with Fetch API”.

Paths and Courses
This exercise can be found in the following Codecademy content:

Learn Full-stack Engineering for your Business
Create a Front-End App with React

Learn Intermediate JavaScript

FAQs on the exercise Making an async GET Request

There are currently no frequently asked questions associated with this exercise – that’s where you come in! You can contribute to this section by offering your own questions, answers, or clarifications on this exercise. Ask or answer a question by clicking reply (reply) below.

If you’ve had an “aha” moment about the concepts, formatting, syntax, or anything else with this exercise, consider sharing those insights! Teaching others and answering their questions is one of the best ways to learn and stay sharp.

Join the Discussion. Help a fellow learner on their journey.

Ask or answer a question about this exercise by clicking reply (reply) below!
You can also find further discussion and get answers to your questions over in Language Help.

Agree with a comment or answer? Like (like) to up-vote the contribution!

Need broader help or resources? Head to Language Help and Tips and Resources. If you are wanting feedback or inspiration for a project, check out Projects.

Looking for motivation to keep learning? Join our wider discussions in Community

Learn more about how to use this guide.

Found a bug? Report it online, or post in Bug Reporting

Have a question about your account or billing? Reach out to our customer support team!

None of the above? Find out where to ask other questions here!

shouldn’t we throw an error ?

1 Like

What’s going on in the renderResponse() helper function? The first 2 if statements to be specific
Is the function parameter meant to be an object or array, I’m lost

Object is object and array is object too.
the function’s parameter is an array of objects:

[{word: "scratch", score: 1001}, {word: "disease", score: 1000}, {word: "fish", score: 999},…]

About the first if I wrote my thoughts two lessons ago=)
The second if checks that array has at least one element in it. If (res.length = 0) then Try again!

Why do we need the second await statement await response.json()?

Are we not already awaiting response? Seems to work without it.

4 Likes

What does the .firstChild() and .removeChild() do at the bottom of the program?

In the html, the div in which the results are to be displayed will be:

<div id="responseField">
</div>

There is an event listener attached to the "submit" button. When the submit button is clicked, displaySuggestions is called.

const displaySuggestions = (event) => {
  event.preventDefault();
  while(responseField.firstChild){
    responseField.removeChild(responseField.firstChild)
  }
  getSuggestions();
}

If the responseField div is empty, then we execute the getSuggestions function.

However, if the results from a previous word search OR some message is present in the div, then we want to clear the div so that we can display the results of the new search.

If there are results from a previous search in the responseField div, then there will be an ordered list with a number of <li> elements. These are considered as the children of the responseField div (parent) element.

If the previous search didn’t return any results, then the responseField will be displaying "<p>Try again!</p><p>There were no suggestions found!</p>". These two <p> elements will be the children of the responseField div in this situation.

See the function renderResponse in the helperFunctions.js file to see how the responseField is being populated.

Elements, whitespace and comments if present all qualify as children.

After the submit button is clicked for new search, removeChild removes the first child of the responseField div. It keeps looping [because of the condition while (responseField.firstChild)] till all children of the responseField div are removed. Once that happens and the div has no more children, then null is returned which means the while condition is no longer true. With the responseField div wiped clean, getSuggestions() is called to process and display the new search results.

See documentation for more details:
https://developer.mozilla.org/en-US/docs/Web/API/Node/firstChild
https://developer.mozilla.org/en-US/docs/Web/API/Node/removeChild

@mtf
why do we use await here: const jsonResponse = await response.json();?

try {
    const response = await fetch(endpoint, {cache: 'no-cache'});
    if(response.ok){
//                         ↓↓↓
      const jsonResponse = await response.json();
//                         ↑↑↑
      renderResponse(jsonResponse);
    }

If we don’t use await, then jsonResponse has the value: [object Promise].

And if we use await, then json Response has the value:
[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]…
And we can refer to the .word property of each object and get the value.

Sorry, I’ve been away. Also must apologize for not being able to properly answer your question since API is not my strong suit. I’m an old timer who learned XHR in the vanilla form, and then later in jQuery, but that was ages ago and I have no more involvement in web development or experience with Promise and Await. @mtrtrk may be able to help you with this one.

1 Like

No problems. Anyway, thanks for the answer.

Can you flesh out your thought process and elaborate a bit more? It might help in identifying your point of confusion.

At the beginning of the try block we declare a variable response, await the resolution of fetch() method. Thus, we get the response object.:

const response = await fetch(endpoint, {cache: 'no-cache'});

In the Intro to GET Requests using Fetch, we were told that response.json() converts the response object to JSON (Actually, mdn web docs use the formulation in the example that we “get JSON value from the response body”).

Why do we await twice?
Why must the “conversion” be asynchronous?
Doesn’t the response variable already contain a finished object?

1 Like

The fetch() method (see documentation) returns a Promise (documentation). The first await

const response = await fetch(endpoint, {cache: 'no-cache'});

is necessary so that instead of the Promise, we can work with the resolved Response (documentation) object. The Response object will include the status, headers, body and other properties of the response. But, the body is actually a ReadableStream (see documentation).

The .json() method (see documentation)

The json() method of the Response interface takes a Response stream and reads it to completion. It returns a promise which resolves with the result of parsing the body text as JSON.

If you omit the second await in your snippet,

//                         ↓↓↓
      const jsonResponse = await response.json();
//                         ↑↑↑

then jsonResponse will be a Promise. But instead of the Promise, we want to work with the result in JSON form. By using the await operator (documentation), we allow the Readable Stream to be read to completion and then allow the Promise to resolve into an object that can be represented as JSON. We can then use this JSON as we are doing in the helper function renderResponse.

Some links to explore:

3 Likes

Thank you for the detailed answer and useful links.
Now everything is clear :slight_smile:

2 Likes

How are we accessing the helper functions in a separate .js file if we’re not importing or exporting them?

It is possible there are two <script/> elements which load two different files. In this instance, everything goes into the same namespace as if it was loaded from one file.

2 Likes

The file navigation icon doesn’t show up for this particular exercise, but if you go back or forward a couple of exercises, you will find the icon in the top left corner of the editor. If you look at the index.html file, you will see:

<script src='https://code.jquery.com/jquery-3.1.0.min.js'></script>
<script src="public/main.js"></script>
<script src="public/helperFunctions.js"></script>

as mentioned by mtf.

2 Likes

Good find.

But wouldn’t the script with helper functions need to be loaded first, so the public/main.js script can call it? The helperFunctions.js file would be globally available to the main.js file if it was above it? Is that right?

Butting in, but only to add more context, not answer the question posed of @mtrtmk. A JS file can contain any number of lines of inline code, along with any number of function declarations or function expressions. Inline code is executed immediately, so if it calls functions that do not exist in the namespace it will throw an exception. This would be the only reason to concern over the order in which JS files load.

An analog of what you are alluding to is the Cascade of CSS. The order in which the files load has a direct effect on the cascade in terms of importance. The last file to load has the highest importance. If all our JS files contain is function and class definitions, and no inline code, it matters not what order we load them. They all go into the same namespace (the stack). Any global variables and data structures are added to the heap.

2 Likes

Thank you for that. Your wisdom is appreciated, sir!

2 Likes