Digging in to jQuery codebase to debug my $.get

So something I didn’t realise when I was learning to code is how I would end up spending my days as a professional developer.

Learning to code is all modelling your domain, writing some tests, writing new code to pass your tests. Very structured and very fun.

Now my days are primarily spent trying to figure out why something doesn’t work as I’d expect it to work. I’ve learned to enjoy this debugging process and so wrote out this case as an example of how I go about it.

The problem

I had already set up the function using Axios to return the processed data so I just got the answer to “isEmailOptedIn.

function isEmailOptedIn(email) {
return axios.get('https://myurl.com/userOptions/email?=' + URIencoded(email)
.then((response) => {
let isOptedIn = response.newsletters.optedIn
return isOptedIn
}

this means from my code I could just ask

isEmailOptedIn(email).then((response) => { let isOptedIn = response }

I quite liked that you could ask the question directly from isEmailOptedIn and get the answer without digging into the data.

Now we also needed to make this call from another part of the codebase where axios was not an option.

So I tried the same thing using jquery’s ajax call.

function isEmailOptedIn(email) {
return $.get('https://myurl.com/userOptions/email?=' + URIencoded(email))
.then((response) => {
let isOptedIn = response.newsletters.typeA
return isOptedIn
})
}

Testing in glitch sandbox

Instead of getting back the boolean (true or false) response I was getting the entire response. { newsletters: { typeA: false, typeB: true } }

IN GLITCH
isEmailOptedIn('kevin@mail.com') // true
IN MY REAL CODEBASE
isEmailOptedIn('kevin@mail.com') // { newsletters: { typeA: false, typeB: false } }

So I noticed the jQuery version on the website is 1.7.1 and the version that was there in the default in glitch was 1.11.1.

I then made another version in glitch using various versions of jQuery and figured out it worked in version 1.8.1

IN GLITCH (jQuery v1.8.1) YAY WORKS
isEmailOptedIn('kevin@mail.com') // true
IN GLITCH (jQuery v1.7.1) BOO NOT WHAT I WANT
actual codebase: isEmailOptedIn('kevin@mail.com') // { newsletters: { typeA: false, typeB: false } }

So at this point deadlines were looming and after bit of investigation I opted to use more traditional callbacks where I added a success function and code worked. But it still niggled.

Diving into jQuery code

Set up two pages on glitch, one pointing to jquery 1.8.1 and one to 1.7.1 with identical code apart from that. both making same ajax call. 1.8.1 returned the final value, while 1.7.1 returned the entire response

two html pages side by side, one with script tag pointing to jquery 1.7.1, the other with script tag pointing to jquery 1.8.1

I used chromes debugging tools and set a breakpoint in the jquery.js file by guessing where I thought an ajax call might end up. (Here’s how to use chrome’s debugger)

I then stepped through the code until I found a promising piece of code (pun intended!)

I then opened both windows and set breakpoint in same place on both and then stepped through on both windows together seeing where they diverged. This led me to a section called

jQuery.extend ({Deferred

I cloned the jquery repo from github onto my local and went through the build instructions in the README.

I copied and pasted the index.html file from glitch into the local repo and pointed at my locally built dist/jquery.js file

I made sure that function was returning the right value on latest build.

I then guessed at the commit in the deferred.js history https://github.com/jquery/jquery/commits/master/src/deferred.js that might taken place between 1.7.1 and 1.8.1 (summer of 2012)

the suspects (a list of commits between late 2011 and early 2012)

I found a commit where it failed from late 2011

Finding the culprit commit

I then made changes until I found the exact line of the commit which made my line fail/work.

By doing this I got to understand the change in the commit and discovered that in trying to get in line with Promises/A, they replaced the functionality that used to be in .pipe and included it in .then

So I could have my functions work the way I wanted them to by updating my code to use .pipe instead of .then!!

function isEmailOptedIn(email) {
return $.get('https://myurl.com/userOptions/email?=' + URIencoded(email))
.pipe((response) => {
let isOptedIn = response.newsletters.typeA
return isOptedIn
})
}

I was incredibly pleased to have tracked down why my code wouldn’t work and also have a solution I can implement.