Javascript函数中的数组范围在内部AJAX循环之外是空的

时间:2016-06-22 00:28:56

标签: javascript jquery arrays ajax

我目前正在阅读How do I return the response from an asynchronous call?,这似乎与我下面的代码无法正常工作的原因有关。 getJSON for循环之后的我的console.log在循环之前执行,因此返回null。 getJSON循环中的console.log返回推入数组的对象。

在多次阅读引用的答案之后,我对如何在回调或承诺中实现解决方案感到困惑。在下面的代码中我需要做什么才能使用回调或promise,以便外部console.log返回数据?

function channel() {
    var channels = ["ESL_SC2", "OgamingSC2", "cretetion", "freecodecamp", "storbeck", "habathcx", "RobotCaleb", "noobs2ninjas"];
    var channelData = [];

    for(var x = 0; x < channels.length; x++) {
        $.getJSON(`https://api.twitch.tv/kraken/channels/${channels[x]}?callback=?`, function(data) {
          console.log(data.display_name);
        //   console.log(data);
          channelData.push( { display_name:data.display_name, logo:data.logo, url:data.url, game:data.game, status:data.status } );
          console.log(channelData);
        });
    }
    console.log(channelData);
}

4 个答案:

答案 0 :(得分:3)

$.getJSON方法返回一个Promise,所以你可以等待所有这些完成。将所有$.getJSON次调用推送到数组中,然后将数组传递给$.when

function channel() {
  var channels = ["ESL_SC2", "OgamingSC2", "cretetion", "freecodecamp", "storbeck", "habathcx", "RobotCaleb", "noobs2ninjas"];
  var channelData = [];
  var gets = [];
  var success = function(data) {
    channelData.push({
      display_name: data.display_name,
      logo: data.logo,
      url: data.url,
      game: data.game,
      status: data.status
    })
  };

  for (var x = 0; x < channels.length; x++) {
    gets.push(
      $.getJSON(`https://api.twitch.tv/kraken/channels/${channels[x]}?callback=?`)
    );
  }
  $.when.apply(null, gets).done(function() {
    var results = arguments;
    for (var i = 0, z = results.length; i < z; i++) {
      var data = results[i][0];
      success(data);
    }
    console.log(channelData);
  });
}

channel()
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>

这里的技巧是$.getJSON返回的内容类似于Promise(它实际上是一个jQuery Deferred对象。另外,在$.when结算之前不会调用成功回调。

因此,您需要将参数解析为传递给$.when的{​​{1}}函数的函数。

不幸的是,这不像done的典型调用那样有效。相反,它实际上是一个带有数字键的对象。这些键的值是通常传递给Promise.all回调的参数数组:即数据,结果文本(“成功”)和jqXHR对象。

因此,我们遍历每个属性并获取第一个值,然后将其传递给解析数据的函数。 Phew:)。

答案 1 :(得分:1)

$ .getJSON是一个异步函数,所以代码在继续之前不会等待它的响应。也就是说,代码将通过 for循环 发出多个异步调用,然后立即调用外部console.log。

getJSON() API documentation

要正确执行外部“console.log”,您必须向通道功能添加一个回调函数,并且只要异步调用有响应,就会调用它。

示例:

function channel(callback) {
    var channels = ["ESL_SC2", "OgamingSC2", "cretetion", "freecodecamp", "storbeck", "habathcx", "RobotCaleb", "noobs2ninjas"];
    var channelData = [];

    for(var x = 0; x < channels.length; x++) {
        $.getJSON(`https://api.twitch.tv/kraken/channels/${channels[x]}?callback=?`, function(data) {
          console.log(data.display_name);;
          channelData.push( { display_name:data.display_name, logo:data.logo, url:data.url, game:data.game, status:data.status } );
          return callback(channelData);
        });
    }
}

channel(function(response) {
    console.log(response); // Where response is your channel Data
    /* do something with the return channel data */
    // Note this function will be called multiple times
})

答案 2 :(得分:1)

function getData(channel){
    return new Promise(function(resolve,reject){
        try{
            $.getJSON(`https://api.twitch.tv/kraken/channels/${channel}?callback=?`, function(data) {
                resolve(data);
            })
        }catch(ex){
            reject(ex);
        }
    })
}
function channel() {
    var channels = ["ESL_SC2", "OgamingSC2", "cretetion", "freecodecamp", "storbeck", "habathcx", "RobotCaleb", "noobs2ninjas"];
    var promises=[];
    for(var x = 0; x < channels.length; x++) {
        promises.push(getData(channels[x]));
    }
    Promise.all(promises).then(datas){
        var channelData = [];
        for(var data in datas){
            channelData.push( { display_name:data.display_name, logo:data.logo, url:data.url, game:data.game, status:data.status } );
        }
        console.log(channelData);
    }
}

答案 3 :(得分:1)

passing an array of deferreds$.when

var channels = ["ESL_SC2", "OgamingSC2", "cretetion", "freecodecamp", "storbeck", "habathcx", "RobotCaleb", "noobs2ninjas"];

$.when.apply($, channels.map(x => $.getJSON(`https://api.twitch.tv/kraken/channels/${x}?callback=?`)))
  .then(function(){
    // here you'll have all the responses
    console.log(arguments)
  })