It's a short post today, based on some conversations I've had with Pablo. Hopefully it helps me remember how jQuery works and maybe anyone else who was just as lost as I was.
In the last post, I wrote:
Then comes the script that loads the plot - I get the data using jQuery's
.getJSON
function. ($
stands for jQuery, which has always been confusing to me.) After not understanding the documentation of this function really at all, I kind of hacked something together. In my understanding, the function/callback .done runs upon a successful completion of getting the JSON, and so I put my plotting code there. If the JSON isn't retrieved, it won't plot.The
.done
function somehow has an input data from the getJSON function - this I don't understand at all.
This is my attempt at explaining .done
.
I won't lie, I find the jQuery documentation to be very hard to understand.
Here is the link for the .getJSON
function - tell me if you can off the bat understand why the .done
method
works, and what arguments are available to the functions it calls.
The first thing to realize is that .getJSON
is really just a convenience
wrapper for a more basic $.ajax
function. Therefore, it makes a lot more sense
to look at the $.ajax
documentation
instead.
From W3:
AJAX is a developer's dream, because you can:
- Read data from a web server - after a web page has loaded
- Update a web page without reloading the page
- Send data to a web server - in the background
Glad that's all cleared up.
.getJSON
?Anyways, we make an AJAX request to the covid_data
route, and I assumed that I
would just get some JSON data in return. That was the limit of my understanding
of the web. It would be in some sort of string representation or something that
the Plotly package could figure out.
That is not the case. What is returned is a
jqXHR,
which is both unpronounceable and also not a string. The jQuery AJAX
documentation further states that as part of the response, there is a .done
callback (note to self - what exactly is a callback), and supplies the
following information:
jqXHR.done(function( data, textStatus, jqXHR ) {})
; An alternative construct to the success callback option, refer todeferred.done()
for implementation details.
deferred.done()
doesn't really help,
except to make it clear that these functions are called after a successful
request. However there is a hint, in the form of (data, textStatus, jqXHR)
in
the function definition.
As an aside, the .done
is necessary because Javascript tries to load
everything asynchronously, thereby populating a web page before every little
part has been loaded. Because of this, you cannot assume that Javascript will
run top to bottom, as it can skip lines if it is waiting and then come back to
them (or at least that is what I understand). The .done
callback makes sure
that if you have code that relies on some response, the response is completed
before the code runs. In our case, the plot cannot be drawn without the data
being fetched. For completeness, there are other callbacks like .fail
,
.always
, and .then
, which execute when the request fails, all the time, and
idk when, respectively.
success
So, deferred.done()
isn't very helpful, but the .ajax
explanation of .done
does actually have a helpful part. Specifically, the part where it says it is
"... an alternative construct to the success callback option..."! Looking at
the success
argument of .ajax
, the documentation says the following:
success
Type: Function( Anything data, String textStatus, jqXHR jqXHR )
A function to be called if the request succeeds. The function gets passed three arguments: The data returned from the server, formatted according to the dataType parameter or the dataFilter callback function, if specified; a string describing the status; and the jqXHR (in jQuery 1.4.x, XMLHttpRequest) object. As of jQuery 1.5, the success setting can accept an array of functions. Each function will be called in turn. This is an Ajax Event.
In the end this solves the mystery of what .done
receives! The functions in
.done
receive the response itself, which is formatted as JSON when using the
.getJSON
wrapper, the status, and the whole jqXHR object (whose purpose I do
not know).
In Javascript, these are implicitly provided, so they can be given any name in the order described above. For example, in my previous post with the interactive plots, I used
1 2 3 4 5 6 7 8 |
|
In this case, the response was called data
, since it was the first argument
provided to function
. I can then use it later in the function. However, it can
be called whatever I like, like new_variable_name
,
1 2 3 4 5 6 7 8 |
|
and the code will still run. new_variable_name
now contains the request from
the the desired URL, correctly formatted as JSON.
One thing that is handy is to play around with this in the browser console. If you open the last post and open the browser console, jQuery will be loaded and you can run something like
1 2 3 |
|
which will print the first argument data
to the console. You'll see that it is
the data that Plotly requires.
If you change data
to something else, you'll see you get the same response -
the JSON response is correctly getting passed to whatever variable you declare!
Mystery solved. I'm not entirely looking forward to a lot more jQuery/Javascript
in my future, but slowly things fit a little bit better together.