Questions on Clementine clickController.client.js

This is the clickController.client.js file from Clementine boilerplate. I am wondering why the method updateClickCount takes in a parameter in its declaration, but in fact there is no argument put into it when it’s been called.

'use strict';

(function () {

   var addButton = document.querySelector('.btn-add');
   var deleteButton = document.querySelector('.btn-delete');
   var clickNbr = document.querySelector('#click-nbr');
   var apiUrl = 'http://localhost:3000/api/clicks';

   function ready (fn) {
      if (typeof fn !== 'function') {
         return;
      }

      if (document.readyState === 'complete') {
         return fn();
      }

      document.addEventListener('DOMContentLoaded', fn, false);
   }

   function ajaxRequest (method, url, callback) {
      var xmlhttp = new XMLHttpRequest();

      xmlhttp.onreadystatechange = function () {
         if (xmlhttp.readyState === 4 && xmlhttp.status === 200) {
            //readystate 4 is "DONE", status 200 denotes a successful request
            callback(xmlhttp.response);
         }
      };

      xmlhttp.open(method, url, true);
      xmlhttp.send();
   }

   function updateClickCount (data) {
      var clicksObject = JSON.parse(data);
      clickNbr.innerHTML = clicksObject.clicks;
   }

   ready(ajaxRequest('GET', apiUrl, updateClickCount));

   addButton.addEventListener('click', function () {

      ajaxRequest('POST', apiUrl, function () {
         ajaxRequest('GET', apiUrl, updateClickCount);
      });

   }, false);

   deleteButton.addEventListener('click', function () {

      ajaxRequest('DELETE', apiUrl, function () {
         ajaxRequest('GET', apiUrl, updateClickCount);
      });

   }, false);

})();

Think of function names as little machines that spit out some product. When you use the name with parens, ie updateClickCount(), you’re pressing the “on” button to start the machine running. When it’s done running, whatever that machine is supposed to make will replace the function name. When you use the name without the parens, ie updateClickCount, you’re handing the machine over to someone else for them to use. More accurately, you’re passing along the function reference. In JavaScript, function names are just variables, so they can be parameters to other functions just like any string, number, or object.

function addTwoNumbers(a,b) {
    return a + b;
}

var result = addTwoNumbers(1, 2); // 3

// copy function by passing reference
var copyOfFunction = addTwoNumbers; // no parentheses means we're not starting the machine, we're just handing it off

var result = copyOfFunction(1,2); // 3

// We can pass the function to another function

// here's a function that doesn't add two numbers by itself, but lets us pass a function that will do it
function putTwoNumbersTogetherSomehow(number1, number2, functionThatPutsNumbersTogether) {
  // all it does is call the function we pass
  return functionThatPutsNumbersTogether(number1, number2);
}

// let's try this again
var result = putTwoNumbersTogetherSomehow(5, 10, addTwoNumbers);  // no parens! we're just handing the machine off for this other function to use

console.log(result); // 15

Check out the code for ajaxRequest. Can you see where the function reference is being used?

updateClickCount is a callback function - the code snippet you posted defines the callback and passes it as a parameter in 3 calls to ajaxRequest - it is not called anywhere in the snippet

Understood! Thank you so much for such an elaborated answer, I really appreciate it and am very grateful :smiley:

Thanks I got it :slight_smile:

callback(xmlhttp.response); here is the ajaxRequest function, and the parameter it passes in is xmlhttp.response

Hi would you minding giving some advice on this one? I’ve got it running on heroku, however, because of the following line of codes from clickController.client.js, I cannot see the number of clicks from the heroku website I deployed.

var apiUrl = ‘http://localhost:3000/api/clicks’;

So I’ve been thinking of a way to make to run both locally and on heroku, without the hassle of changing codes. Since I only know that when the source codes are uploaded to heroku, the variable process.env.PORT would contain some value instead of a null value as in local. I’ve tried to modify it into this:

var apiUrl = ((process.env.PORT) ? ‘https://clementinecheck.herokuapp.com/’ : ‘http://localhost:3000’) + ‘/api/clicks’;

Yet it gives me error on this exact line saying that process is not defined. I’ve check nodejs’ documentation of the process variable, it says that it’s a global object, so I thought it should be accessible from ./app/clickController.client.js right? Anything that I’m missing?

You can use a relative URL.

var apiUrl = "/api/clicks";

Ah, I see. I should’ve realized.:sweat_smile: