-1

I have been stuck for far too long on the following problem that I really need to consider my theoretical knowledge about variable scope and callback functions in Javascript. Rather than a quick fix for my particular problem a generalized answer that tries to explain the theory behind my problem is preferred. Here is the code (that doesn't work) (oh and it uses jQuery's $.getJSON).

function getStreamerStatus(streamer) {
  var channelurl = "https://api.twitch.tv/kraken/channels/";
  var streamurl = "https://api.twitch.tv/kraken/streams/";
  var temporary = {
    status: "",
    game: "",
    picture: "",
    name: streamer,
    link: "https://www.twitch.tv/" + streamer
  };

  $.getJSON(streamurl + streamer, createCallback(temporary));
  $.getJSON(channelurl + streamer, createCallback(temporary));

  return temporary;
}

After some searching I used the "createCallback()" function in an attempt to make the "temporary" object visible to the callback function.

function createCallback(tmpobj) {
  return function(json) {
    //get's some information and stores it in the object passed as tmpobj
    filterOut(json, tmpobj);
  };
}

And in the end in the main function I have an array with names of twitch streamers and for each name the "getStreamerStatus()" function is called and the returned object is stored in an array.

function TwitchInit() {
  var channels = [/*filled with strings of streamer names*/];
  var response = []; //array with objects with all the information

  for(var i = 0; i < channels.length; i++) {
    response.push(getStreamerStatus(channels[i]));
  }
  parseContent(response); //not relevant for now

  //for debugging
  for(var j = 0; j < response.length; j++) {
    console.log("--responseArray with Objects--");
    for(var prop in response[j]) {
      if(response[j].hasOwnProperty(prop)) {
        console.log(prop + ": " + response[j][prop]);
      }
    }
  }
}

The problem here is that if I log the objects to the console only the "link" and "name" properties of the objects have some content and the other properties who're supposed to be written by the "filterOut()" function always remain empty. According to the console the communication with the Twitch server is fine and I can read the response header/object from the console so that rules out. And since the "name" and "link" properties are also different at each log to the console that means that each time a new object is created which is fine. That leads me to the conclusion that the "temporary" object still somehow isn't visible to the callback function inside $.getJSON despite my attempt with "createCallback()" to make the object visible to the "filterOut()" function. I have found a lot of information about variable scope in JavaScript but so far it hasn't helped my to solve my problem. I have no clue what I am doing wrong here and I'm starting to get frustrated. I really hope someone can enlighten me here.

Blackbird
  • 9
  • 4
  • Try `new temporary()` as an argument to `createCallback()` so the results from the first query don't overwrite the second. Also, `createCallback()` seems to return a function (not the output of a function, especially since the function is never run). I don't see where the value of `json` is supposed to be coming from. `createCallback` certainly doesn't know what that is. Your post should also include the form of the output you expected to get and the output you actually got . – LinuxDisciple Apr 07 '16 at 21:02
  • Can you show you function filterOut too ? it seems to be the one filling your data – user3 Apr 07 '16 at 21:04
  • @user3 He had it earlier, then removed it. It's in the edit history if you want it. I'm pretty sure it never runs though. – LinuxDisciple Apr 07 '16 at 21:06
  • @LinuxDisciple I just look at it, thanks, you're right the problem does not seems to come from it – user3 Apr 07 '16 at 21:09
  • From what I can see, it seems to work, create callback returns a function that take just a json, and $.getJSON expect a function that takes a json, so it's ok – user3 Apr 07 '16 at 21:17
  • There is no problem with functions, scopes or closures here. It's just asynchrony at work - and [`console.log` giving confusing output](http://stackoverflow.com/q/23392111/1048572) – Bergi Apr 08 '16 at 14:47

1 Answers1

0

I think there is no problem is closure here, the only problem is that your getStreamerStatus function will perform async tasks but will return a value directly, and use it without waiting the async calls (getJSON) to complete.

Try to put you debug logs inside a setTimeout with few seconds delay ;)

To so things better you should rewrite your getStreamerStatus to only returns the data after the getJSON calls are done, not before, with a callback as parameter, or by returning a promise.

Or you should have something (ie: an event) to tell your function that the calls are finished, and that it can process the results.

user3
  • 740
  • 3
  • 15
  • Even if `getStreamerStatus()` waited until both callbacks returned, and even if `getCallBack()`/`filterOut()` successfully modified `temporary`, there's still only one `temporary` object, so it could only hold the results of one transaction at a time. – LinuxDisciple Apr 07 '16 at 21:29
  • yes, but the request are on 2 differents urls, so it is possible that he wants to take some info from one source, some from one another, and to aggregate that into one object, the "temporary" one, otherwise yes it won't work as expected but I'm missing too much details to know – user3 Apr 07 '16 at 21:36
  • 1
    @user3 I'm sorry for the lack of details I thought too many details would just be distracting from the root problem. However after some further search I found a very good answer here: http://stackoverflow.com/a/14220323/5754117 which basically makes my question obsolete. But thank's anyway for the help guys ;) You were pointing in the right direction with the async calls. – Blackbird Apr 08 '16 at 06:21