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 AJAX Basics (retiring) Programming AJAX Stage 2 Challenge

Bruno Dias
Bruno Dias
10,554 Points

Can I create a callback function last?

I am wondering if I could create the XHR request first, open the request, send the request and then add a callback function to handle with the response.

Is it Ok to do this way?

var myRequest = new XMLHttpRequest();

myRequest.open('GET', 'data/myfile.json');

myRequest.send();

myRequest.onreadystatechange = function() {
  if (myRequest.readyState === 4) {
    var rooms = JSON.parse(roomRequest.responseText);
    console.log(rooms);
  }
}

1 Answer

Rick Buffington
Rick Buffington
8,146 Points

No, it is generally not okay to do it that way.

Remember, your browser reads the code from HTML and JavaScript files IN ORDER of appearance. So, if you are wanting something to happen but haven't declared it BEFORE the action, nothing will happen. :) The order of events and callbacks is important in JavaScript.

Bruno Dias
Bruno Dias
10,554 Points

Thanks for clarifying. As I understand In AJAX the onreadystatechange is called after the server sends the response, is that right?

Brendan Moran
Brendan Moran
14,052 Points

Bruno Degaspare, onreadystatechange is called whenever the ready state changes. There are 5 total ready states. The final ready state change is when the response has returned from the server and is ready to be used. It is highly unlikely but perhaps possible that the response comes back and is ready before the browser gets on to reading your callback. In this case, there would be no further ready state change and your function would never be called. You can place your event listener after your .open() statement to forego one useless call on your onreadystatechange event handler, but from what I've observed, the event listener is always before the .send() method. You can include your callback as an anonymous function, or you can declare a function earlier in your code that you ask the event listener to call later, like this:

var employeeListDiv = document.getElementById("employeeList"),
    roomListDiv = document.getElementById("roomList"),
    employeeStatusXHR = new XMLHttpRequest(),
    roomStatusXHR = new XMLHttpRequest();

function employeeStatusCallback() {
  if (employeeStatusXHR.readyState === 4 && employeeStatusXHR.status === 200) {
    var employees = JSON.parse(employeeStatusXHR.responseText),
        ul = document.createElement("ul");
    ul.classList.add('bulleted');
    for (var i = 0, length = employees.length; i < length; i++) {
      var listItem = document.createElement("li"),
          liClassList = listItem.classList;
      listItem.textContent = employees[i].name;
      if (employees[i].inoffice === true) {
        liClassList.add('in');
      } else {
        liClassList.add('out');
      }
      ul.appendChild(listItem);
    }
    employeeListDiv.appendChild(ul);
  }
}

function roomStatusCallback() {
   if (roomStatusXHR.readyState === 4 && roomStatusXHR.status === 200) {
    var rooms = JSON.parse(roomStatusXHR.responseText),
        ul = document.createElement("ul");
    ul.classList.add("rooms");
    for (var i = 0, length = rooms.length; i < length; i++) {
      var listItem = document.createElement("li"),
          liClassList = listItem.classList;
      listItem.textContent = rooms[i].room;
      if (rooms[i].available === true) {
        liClassList.add("empty");
      } else {
        liClassList.add("full");
      }
      ul.appendChild(listItem);
    }
    roomListDiv.appendChild(ul);
  }
}

employeeStatusXHR.open('GET', 'data/employees.json');
employeeStatusXHR.onreadystatechange = employeeStatusCallback;
employeeStatusXHR.send();

roomStatusXHR.open('GET', 'data/rooms.json');
roomStatusXHR.onreadystatechange = roomStatusCallback;
roomStatusXHR.send();