【问题标题】:Accessing array / scope of variable [duplicate]访问变量的数组/范围[重复]
【发布时间】:2015-09-21 13:49:15
【问题描述】:

我正在尝试填充一个数组并稍后使用它。当我尝试访问索引处的对象时,我得到“未定义”的结果。

$(document).ready(function() {

  var streamers = ["freecodecamp", "GeoffStorbeck", "terakilobyte"];

  var cb = '?client_id=5j0r5b7qb7kro03fvka3o8kbq262wwm&callback=?';
  var url = 'https://api.twitch.tv/kraken/';
  var result = {};


  streamers.forEach(function(stream)
  {
    $.getJSON(url + 'streams/' + stream + cb).success(function(data)
    {
        var streaming = (data.stream === null) ? false : true;
        result.push(stream + " - " + streaming);
    });
  });

  alert(result[0]);
  alert(result[1]);
  alert(result[2]);
});

【问题讨论】:

标签: javascript arrays json scope


【解决方案1】:

您需要的是一个callback,因为您为服务器获取的东西主要发生在asynchronous 进程中,这意味着代码会继续执行并且只有在返回某些东西时才会向数组添加一些东西。您希望脚本仅在完成任务时发出警报,这就是我们将其称为回调的原因,因为它会 call 传递的函数 back(也就是当它完成)。

$(document).ready(function() {

  var streamers = ["freecodecamp", "GeoffStorbeck", "terakilobyte"];

  var cb = '?client_id=5j0r5b7qb7kro03fvka3o8kbq262wwm&callback=?';
  var url = 'https://api.twitch.tv/kraken/';
  // This should be initialised as an array, not an object!
  var result = [];
  
  function callback(){
    // I add this line to reduce the amount of alerts
    if(result.length !== 3) return;
    alert(result[0]);
    alert(result[1]);
    alert(result[2]);
  }


  streamers.forEach(function(stream){
    $.getJSON(url + 'streams/' + stream + cb).success(function(data){
        var streaming = (data.stream === null) ? false : true;
        result.push(stream + " - " + streaming);
        callback();
    });
  });
});

【讨论】:

  • 啊,确实!我的错。
  • 另外我会用成功来做下一个电话
  • @mplungjan 是的,你可以,但就本示例而言,这不是必需的。这样做会更好,但是由于我正在检查长度,因此最终结果没有区别。
  • 我同意@somethinghere - 当你开始处理结果时,最好改变它的工作方式。但现在它回答了关于查看数据的问题。虽然我认为我的答案更好:P
  • @AdrianLynch 我喜欢你的回答,也赞成它——它更能解释异步恕我直言。
【解决方案2】:

您正在访问result 之前 $.getJSON 回调已执行。很多类似的问题已经得到解答,请参阅Why is my variable unaltered after I modify it inside of a function? - Asynchronous code reference 了解问题的解释。

您应该利用所有 Ajax 方法都返回 promises/deferred objects 并使用 $.when 等待它们全部完成的事实:

var deferreds = streamers.map(function(stream) {
  return $.getJSON(url + 'streams/' + stream + cb).then(function(data) {
    var streaming = (data.stream === null) ? false : true;
    return stream + " - " + streaming;
  });
});

$.when.apply(null, deferreds).then(function(result) {
  console.log(result);
});

【讨论】:

  • 比仅仅等待结果被填充更好但更难理解的承诺
【解决方案3】:

$.getJSON 是异步的。

在数组中有数据之前,您的警报正在运行。

要在数据可用时查看数据,请将警报(或者更好的是,console.logs)向上移动到成功回调中:

$(document).ready(function() {

    var streamers = ["freecodecamp", "GeoffStorbeck", "terakilobyte"];
    var cb = '?client_id=5j0r5b7qb7kro03fvka3o8kbq262wwm&callback=?';
    var url = 'https://api.twitch.tv/kraken/';
    var result = {};

    streamers.forEach(function(stream) {
        $.getJSON(url + 'streams/' + stream + cb).success(function(data) {
            var streaming = (data.stream === null) ? false : true;
            result.push(stream + " - " + streaming);
            console.log(result);
        });
    });
});

从查看结果转移到使用结果,您需要稍微分解一下:

$(document).ready(function() {

    var streamers = ["freecodecamp", "GeoffStorbeck", "terakilobyte"];
    var cb = '?client_id=5j0r5b7qb7kro03fvka3o8kbq262wwm&callback=?';
    var url = 'https://api.twitch.tv/kraken/';
    var result = {};

    var getStreams = streams.map(function (stream) {
        return $.getJSON(url + 'streams/' + stream + cb).success(function(data) {
            var streaming = (data.stream === null) ? false : true;
            result.push(stream + " - " + streaming);
            console.log(result);
        });
    });

    var onResultsSuccess = function (results) {
        console.log("I have all my streams, let's take a look at them:", results);
    };

    var onResultsFail = function () {
        console.log("Something's up!", arguments);
    };

    $.when(getStreams).then(onResultsSuccess, onResultsFail);

});

未经测试所以假设它是伪的!

【讨论】:

    【解决方案4】:

    您不仅应该将警报推迟到调用之后,而且您不应该在外部循环 Ajax..

    这是我的建议

    function getStream() {
       if (result.length >= streamers.length) return;
       var stream = streamers[result.length];
       $.getJSON(url + 'streams/' + stream + cb).success(function(data){
         var streaming = (data.stream === null) ? false : true;
         result.push(stream + " - " + streaming);
         getStream();
       });
    }
    var streamers = ["freecodecamp", "GeoffStorbeck", "terakilobyte"];
    var cb = '?client_id=5j0r5b7qb7kro03fvka3o8kbq262wwm&callback=?';
    var url = 'https://api.twitch.tv/kraken/';
    // This should be initialised as an array, not an object!
    var result = [];
    $(function() {
      getStream();      
    });
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-06-09
      • 1970-01-01
      • 1970-01-01
      • 2021-12-04
      • 2017-03-10
      相关资源
      最近更新 更多