使用JavaScript回调函数了解变量范围和闭包

时间:2016-04-07 20:38:20

标签: javascript scope callback closures

我在以下问题上被困了太长时间,我真的需要考虑我在Javascript中关于变量范围和回调函数的理论知识。而不是快速解决我的特定问题,而是试图解释我的问题背后的理论的广义答案是首选。这是代码(不起作用)(哦,它使用jQuery的$ .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;
}

经过一些搜索,我使用了“createCallback()”函数,试图让“临时”对象对回调函数可见。

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

最后在main函数中我有一个名为twitch streamers的数组,每个名称调用“getStreamerStatus()”函数,返回的对象存储在数组中。

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]);
      }
    }
  }
}

这里的问题是,如果我将对象记录到控制台,只有对象的“链接”和“名称”属性具有一些内容,而其他属性应该由“filterOut()”写入功能始终保持空白。根据控制台,与Twitch服务器的通信很好,我可以从控制台读取响应头/对象,以便排除。并且由于每个日志到控制台的“名称”和“链接”属性也不同,这意味着每次创建一个新对象都很好。这让我得出这样的结论:“临时”对象仍然以某种方式对$ .getJSON内部的回调函数不可见,尽管我尝试使用“createCallback()”使对象对“filterOut()”函数可见。我在JavaScript中找到了很多关于变量范围的信息,但到目前为止它还没有帮助我解决我的问题。我不知道我在这里做错了什么,我开始感到沮丧。我真的希望有人能在这里启发我。

1 个答案:

答案 0 :(得分:0)

我认为这里的闭包没有问题,唯一的问题是你的getStreamerStatus函数会执行异步任务,但会直接返回一个值,并在不等待异步调用(getJSON)完成的情况下使用它。

尝试将调试日志放在setTimeout中,延迟时间为几秒;)

为了做得更好,你应该重写你的getStreamerStatus,只在getJSON调用完成后返回数据,而不是之前,使用回调作为参数,或者返回一个promise。

或者你应该有一些东西(即:一个事件)来告诉你的函数调用已经完成,并且它可以处理结果。