A little backstory, I'm using the Twitch (game streaming service) api to pull a list of followers from a channel on the site. In order to get around the CORS rules I'm using JSONP. Personally, I prefer to use vanilla javascript over libraries so I learned how to do it from the excellent article over on https://cameronspear.com/blog/exactly-what-is-jsonp/ .
Below is my simplified javascript (the actual code probably isn't extremely necessary, but maybe it'll help to clarify my question afterward):
//Function to pull JSONP
function pullJSONP(url) {
var JSONPInstance = document.createElement('script');
JSONPInstance.src = url;
JSONPInstance.onload = function () {
this.remove();
};
var head = document.getElementsByTagName('head')[0];
head.insertBefore(JSONPInstance, null);
}
//End function to pull JSONP
function storeCurrentFollows(offset) //Function to wrap entire operation
{
function pullStartSessionFollows(JSONdata) //Callback from JSONP down below
{
function pushNameElements(followEntry) //Function to add names into array
{
allSessionFollows.push(followEntry.user.name);
}
JSONdata.follows.forEach(pushNameElements); //Iterate through followers
storeCurrentFollows(offset+100); //Rerun operation, incrementing offset by 100
};
if(offset > 300){ return }
else
{
//running JSONP function from above, passing in url and setting a callback
pullJSONP('https://api.twitch.tv/kraken/channels/' + channelName + '/follows?direction=desc&limit=100&offset=' + offset + '&callback=pullStartSessionFollows');
}
}
storeCurrentFollows(0);
So my question is this, whenever I run this operation with the items in this order it returns the error > Uncaught ReferenceError: pullStartSessionFollows is not defined
in the console. It doesn't work properly unless I move the pullStartSessionFollows
function up into the global scope. What I don't understand is why it thinks it is undefined even though it is instantiated just before I run the pullJSONP() function. I don't want to move it because then I'll have to pass in my offset to two different functions as well as a few other issues. Any help or insight would be very much appreciated. Thank you in advance!
It doesn't work properly unless I move the pullStartSessionFollows function up into the global scope.
Correct, JSONP callbacks must be global functions. It's intrinsic to the way JSONP works.
What I don't understand is why it thinks it is undefined even though it is instantiated just before I run the pullJSONP() function.
Because that creates the function within the function where you do that (storeCurrentFollows
), not as a global. But the way JSONP works requires that the function be global.
You can have the pullStartSessionFollows
function only exist while you have a pending JSONP call, by declaring it as a global variable:
var pullStartSessionFollows;
...and then assigning to that within storeCurrentFollows
:
pullStartSessionFollows = function() { /* ... */ };
You can also remove it when the callback has done its work:
pullStartSessionFollows = undefined;
Why must the callback function be a global? Because the way JSONP works is by adding a script element to the page, as though you had written this in the HTML:
<script src="http://example.com/get?callback=pullStartSessionFollows"></script>
...and then the response looks like:
pullStartSessionFollows({/*...JSON here...*/})
That requires that it be a global function.