bugfix> javascript > 投稿

チャンネル名の配列(user_arr)があり、twitch.tvから詳細を取得する必要があります

コードは以下の詳細をお読みください

$(document).ready(function(){
var user_arr = ["ESL_SC2", "OgamingSC2", "cretetion", "freecodecamp", "storbeck", "habathcx", "RobotCaleb", "noobs2ninjas"]

  var newarr =[];
  var streams  = [];
  var channels = [];
for(var i = 0 ; i < user_arr.length; i++){ 
    name = user_arr[i];

var url1 ="https://wind-bow.gomix.me/twitch-api/streams/"+name+"?callback=?"
var url2 ="https://wind-bow.gomix.me/twitch-api/channels/"+name+"?callback=?"

$.ajax({
  type:"GET",
  url:url1,
  dataType:"json",
  async:false,
  success:function(streamed_data){
    streams.push(streamed_data);
  }

});

     $.ajax({
  type:"GET",
  url:url2,
  dataType:"json",
  async:'true',
  success:function(channel_data){
    channels.push(channel_data);
  }

});

     }
console.log(channels);
console.log(channels[1]);
});

コードからわかるように、jsonで詳細を取得しようとしていますが、どうやら詳細を新しい配列にプッシュすると、user_arrと同じ方法ではプッシュされません。どちらが先に受信された順にプッシュされていると思います

私はjqueryを使用していますが、この問題について多くの人に尋ねましたが、ほとんどの回答は約束に関するものでした(私は理解しておらず、使用方法がわかりません)

加えて、console.log(channels);データで満たされた配列を表示しています しかし、直前のコマンドの直後にconsole.log(channels.length)を実行すると、長さが0になり、データが表示されません

$.getJSONと同様に$.ajaxを使用して、元の配列の順序でデータを取得するための最良の方法は何ですか?

最終的な配列にマップ関数を適用して配列を再配置しようとしましたが、失敗しました

user_arr配列に基づいて最終的な配列を取得するために、マップ関数を配列に適用する方法を誰かが教えてくれると本当に助かります

回答 3 件
  • async: false は可能ですが  問題を解決できる可能性がありますが、実行可能なソリューションではありません。 UIスレッドの更新をブロックし、リクエストの進行中にブラウザがハングしたように見せるため、これはひどい習慣です。

    はるかに優れたソリューションは、非同期パターンを適切に処理し、すべての要求をPromiseの配列に集約することです。これらの約束が解決されたら(つまり、すべてのリクエストが完了したら)、 channel をソートできます。  および streams   display_names の順序と一致する配列   user_arr に含まれる 。これを試して:

    var user_arr = ["ESL_SC2", "OgamingSC2", "cretetion", "FreeCodeCamp", "storbeck", "habathcx", "RobotCaleb", "noobs2ninjas"]
    var newarr = [];
    var streams = [];
    var channels = [];
    var promises = user_arr.map(function(username) {
      var deferred = $.Deferred();
      var url1 = `https://wind-bow.gomix.me/twitch-api/streams/${username}?callback=?`;
      var url2 = `https://wind-bow.gomix.me/twitch-api/channels/${username}?callback=?`;
      $.when($.ajax({
        type: "GET",
        url: url1,
        dataType: "json",
        success: function(streamed_data) {
          streams.push(streamed_data);
        }
      }), $.ajax({
        type: "GET",
        url: url2,
        dataType: "json",
        success: function(channel_data) {
          channels.push(channel_data);
        }
      })).done(function() {
        deferred.resolve();
      });
      return deferred.promise();
    });
    $.when.apply($, promises).done(function() {  
      channels.sort(function(a, b) {
        return user_arr.indexOf(a.display_name) > user_arr.indexOf(b.display_name);
      });
      
      streams.sort(function(a, b) {
        return user_arr.indexOf(a._links.channel.display_name) > user_arr.indexOf(b._links.channel.display_name);
      })
      
      console.log(channels);
      console.log(streams);
    });
    
    
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    
    

  • これでうまくいくはずですが、ちょっとしたおもちゃでこれ以上やることを計画しているなら、約束を学ぶことを本当にお勧めします。

    var user_arr = ["ESL_SC2", "OgamingSC2", "cretetion", "FreeCodeCamp", "storbeck", "habathcx", "RobotCaleb", "noobs2ninjas"]
    var streams = [];
    var channels = [];
    var count = 0;
    function done() {
      count++;
      if (count === user_arr.length * 2) {
        console.log(streams);
        console.log(channels);
      }
    }
    function getData(userName, index) {
      var url1 = "https://wind-bow.gomix.me/twitch-api/streams/" + name + "?callback=?"
      var url2 = "https://wind-bow.gomix.me/twitch-api/channels/" + name + "?callback=?"
      $.ajax({
        type: "GET",
        url: url1,
        dataType: "json",
        async: true,
        success: function(streamed_data) {
          streams[index] = streamed_data;
          done();
        }
      });
      $.ajax({
        type: "GET",
        url: url2,
        dataType: "json",
        async: true,
        success: function(channel_data) {
          channels[index] = channel_data;
          done();
        }
      });
    }
    for (var i = 0; i < user_arr.length; i++) {
      name = user_arr[i];
      getData(name, i);
    }
    
    
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    
    

    配列をログに記録したときに空だったため、ログは奇妙に見えますが、長さではなく配列全体をログに記録すると、devtoolsは後で行われた変更を反映しています。

  • 私が思いつくことができる約束の最も良い使用法を含む別の答え。

    注: Promise  Internet Explorerを除くすべてのユーザー(はい、エッジも)によってサポートされています。 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise

    これをJQuery $.whenにマッピングする方法がわからないため、IEサポートが必要な場合は、それを把握する必要があります。

    var user_arr = ["storbeck", "habathcx", "RobotCaleb", "noobs2ninjas"]
    function getStreams(userName) {
      var url1 = "https://wind-bow.gomix.me/twitch-api/streams/" + userName + "?callback=?" ; 
      return $.ajax({
        type: "GET",
        url: url1,
        dataType: "json",
        async: true
      });
    }
      
    function getChannels(userName) {
      var url2 = "https://wind-bow.gomix.me/twitch-api/channels/" + userName + "?callback=?";
      return $.ajax({
        type: "GET",
        url: url2,
        dataType: "json",
        async: true
      });
    }
    var streamPromise = Promise.all(user_arr.map(getStreams))
    var channelPromise = Promise.all(user_arr.map(getChannels))
    Promise.all([streamPromise, channelPromise]).then(function(results){
      const streams = results[0];
      const channels = results[1];
      
      //do what you need to do
      console.log('users:', user_arr);
      console.log('streams:', streams);
      console.log('channels:', channels);
    });
    
    
    .as-console-wrapper { max-height: 100% !important; top: 0; }
    
    
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    
    

あなたの答え