访问数组/变量的作用域

Accessing array / scope of variable

本文关键字:作用域 变量 数组 访问      更新时间:2023-09-26

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

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

您需要的是callback,因为您为服务器获取的内容主要发生在asynchronous进程中,这意味着代码继续执行,只有在返回内容时才向数组添加内容。您希望脚本只在完成任务时发出警告,这就是为什么我们称之为回调,因为它将调用传递的函数返回(也就是当它完成时)。

$(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();
    });
  });
});

在执行$.getJSON回调之前正在访问result 。许多类似的问题已经得到了回答,参见为什么我的变量在函数内部修改后没有改变?-异步代码参考,用于解释问题。

您应该利用所有Ajax方法返回承诺/延迟对象的事实,并使用$.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);
});

$.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);
});

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

不仅应该将警报延迟到调用之后,还不应该在外部循环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();      
});