Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

JavaScript Asynchronous Programming with JavaScript Asynchronous JavaScript with Callbacks Implement a Callback

Roald Jurrian Kamman
seal-mask
.a{fill-rule:evenodd;}techdegree seal-36
Roald Jurrian Kamman
Front End Web Development Techdegree Graduate 15,543 Points

I still don't understand how arguments work.

I'm currently going through some of the callback function videos and everything works which is wonderful.

I just don't know WHY or HOW it works. So I will never be able to replicate this in a real-world scenario where it's not already done for me.

Let's take a look at some code examples to explain exactly what I don't understand I added in some comments:

//example 1

const astrosUrl = 'http://api.open-notify.org/astros.json';
const wikiUrl = 'https://en.wikipedia.org/api/rest_v1/page/summary/';
const peopleList = document.getElementById('people');
const btn = document.querySelector('button');

// Make an AJAX request
function getJSON(url, callback) {
  const xhr = new XMLHttpRequest();
  xhr.open('GET', url);
  xhr.onload = () => {
    if(xhr.status === 200) {
      let data = JSON.parse(xhr.responseText);
       // the (data) argument is a variable I understand why passing that as an argument 
       //works. 
      // However I don't know why or how the callback argument works. 
      return callback(data);
    }
  };
  xhr.send();
}

function generateHTML(data) {
// here the (data) argument is not in a variable due to scope it was only defined in the other //function. 
  const section = document.createElement('section');
  peopleList.appendChild(section);
  section.innerHTML = `
    <img src=${data.thumbnail.source}>
    <h2>${data.title}</h2>
    <p>${data.description}</p>
    <p>${data.extract}</p>
  `;
}

//example 2

btn.addEventListener('click', () => { 
  getJSON(astrosUrl, (json) => {
    console.log(json)
// the (json) argument. I tested changing json to whyTheFuckDoesThisWork and it still //worked. How does simply passing any variable tell the console exactly what to log?
  });
});

I'm just kind of lost. I understand that arguments are useful and that we can pass a variable as an argument. I just don't understand the nearest thing on how they work or why they work or how JavaScript determines what exactly to do with the arguments.

I have been learning JavaScript for months now and whenever I feel like I understand it a bit I feel like I run into a wall again and again...

Documentation on parameters isn't very useful either in this regard.

Is there a way to do any of this without using arguments? Don't really care if that increases the number of variables and functions tenfold as long as I can see what is communicating with what and how it's doing that.

Also how does one keep track of the functions within functions within functions. How do I train my brain for all this inception? Is a parameter affected if it's a function inside another function? Like in example 2 getJSON is called. Do the parameters of that function effect the parameters of this function? How does JavaScript know which data to grab? Why doesn't it console.log any of the other information that it can possibly grab?

Right now these arguments/parameters just look like magic words that do exactly what's necessary. But WHY?

I'm sorry that one question turned into 10. The more I looked into this the worse my confusion about it got.

4 Answers

Trying to skip parameters and arguments will not help you in anyway. Learning about them and how to use them is not only crucial for your own code but in the event that you read someone else's code as well.

Hopefully this helps https://w.trhou.se/rglkdiyjko

Roald Jurrian Kamman
seal-mask
.a{fill-rule:evenodd;}techdegree seal-36
Roald Jurrian Kamman
Front End Web Development Techdegree Graduate 15,543 Points

I agree, I never intended to skip it but I don't grasp completely how they work. It's wonderful that they grab data passed from functions. But in any case, there is SO MUCH DATA that they pass on. How do I know which data will be used in which case? JavaScript seems to intelligently choose the right data that's being passed by an argument. a good example is a DOM scripting event with a name variable being passed to fill in the blanks: Hello "___" how are you today? In this example we give it a name by filling in the variable through passing an argument in a function. But why does it grab other data in other real-life examples and how does it choose which data to pick. Exactly what is the extent of the data being grabbed by an argument? In the example, the only data available is the string we pass it. But in other cases, you could pass all the information from any function. That's potentially infinitely more data being passed through one argument. How does it know what to use? Why does JavaScript choose to use the data that it chooses? Those are all things I'm yet to find out. I have spent days reading the documentation on arguments and am still to find any of this.

Roald Jurrian Kamman
seal-mask
.a{fill-rule:evenodd;}techdegree seal-36
Roald Jurrian Kamman
Front End Web Development Techdegree Graduate 15,543 Points

After reading and thinking about what you wrote thoroughly I do have a better understanding of how they work. Awesome! I'm still lost on most of the things I wrote in my first comment. I would really appreciate if you could help me with any of those questions. :) But maybe you know of a resource I don't have yet. I might've spent days reading the documentation but the internet is a big place.

Thanks

Blake Larson
Blake Larson
13,014 Points

In this code the xhr.status is 200 so the the callback that is sent into the getJSON function is triggered which logs the data to the console in the event listener. The naming doesn't have to be the same and you can add to it like this. Sometimes it will be an error message.

xhr.onload = () => {
    if(xhr.status === 200) {
      let data = JSON.parse(xhr.responseText);
       // the (data) argument is a variable I understand why passing that as an argument 
       //works. 
      // However I don't know why or how the callback argument works. 
      return callback(weirdVariableName, 'Meaningless string to pass along');
    }
  };

btn.addEventListener('click', () => { 
  getJSON(astrosUrl, (someOtherVar, str) => {
    console.log(str);
    if(str) {  // <-------- 'Meaningless string to pass along'
       console.log(someOtherVar);
    }

  });
});

Basically the naming of it doesn't matter but the order will if you are sending multiple arguments back. Also don't get too hung up on callbacks because you will be learning a bunch of async JavaScript and now promises and asyn/await are taking over so don't worry to much.

Blake Larson
Blake Larson
13,014 Points

Here is a maybe an easier example of how the callbacks and it's arguments are used. This isn't really useful but explains the asynchronous nature.

observeString() takes a string and checks if it if it starts with an 'a', has more than 10 characters and is more than one word. If it is the callback is returned with a true value, else false. You then handle that in the call back to log if the string meets the requirements.

You will see "This log statement fires first because it is synchronous" in the console and then after 1.5 seconds you will see "This string has more than 10 characters starts with an 'a' and has multiple words" because "apple computer" passes.

function observeString(str, callback) {
  const longerThanTen = str.length > 10;
  const startsWithA = str[0].toLowerCase() === "a";   // String check 
  const containsSpaces = str.trim().includes(" ");

  setTimeout(() => { // 1.5 second timeout
    if (longerThanTen && startsWithA && containsSpaces) {
      return callback(true);
    }
    return callback(false);
  }, 1500);

// First to log because it's first in the stack
  console.log("This log statement fires first because it is synchronous");
}

function originalCaller() {
  observeString("apple computer", (bool) => { 
    if (bool) {
      console.log(
        "This string has more than 10 characters starts with an 'a' and has multiple words"
      );
    } else {
      console.log("This string is missing one of the requirements");
    }
  });
}

originalCaller(); // <---- Starts the chain with initial function call