

js初心者です。初歩的な質問かもしれませんがご容赦下さい。

CSVに格納しておいた複数のGoogleCalendarのID情報を読み込んできて、  
そこからfor分を使ってループ処理をかけて、各カレンダーの情報を取り出す処理を考えました。

なぜかわからないのですが、カレンダー情報は取り出せるのですが、  
CSVからID情報と付随して取得したランク情報がうまく反映されません。

コールバック関数やdefferを関数で使う形を調べましたが、  
いまいちしっくりと来ませんでした。

お手数ですが、ご尽力お願い致します。

**問題点：**

実際に出力すると、irankの変数だけ挙動がおかしい。`data.items[0].summary`は特に問題なし。  
→CSV最終行の文字列（`irank = csvListall[263][5] = b`）の値が全ての`irank`で代入されてしまう。

**今回求める結果：**

[code]

    a +文字列（data.items[0].summaryの結果← i=0のとき
    b +文字列（data.items[0].summaryの結果← i=1のとき
    ss+文字列（data.items[0].summaryの結果← i=2のとき
    c +文字列（data.items[0].summaryの結果← i=3のとき
    b +文字列（data.items[0].summaryの結果← i=4のとき
    ss+文字列（data.items[0].summaryの結果← i=5のとき
    s +文字列（data.items[0].summaryの結果← i=6のとき
    ↓
    続く...
    
[/code]

**結果：**

[code]

    b+文字列（data.items[0].summaryの結果← i=0のとき
    b+文字列（data.items[0].summaryの結果← i=1のとき
    b+文字列（data.items[0].summaryの結果← i=2のとき
    b+文字列（data.items[0].summaryの結果← i=3のとき
    b+文字列（data.items[0].summaryの結果← i=4のとき
    b+文字列（data.items[0].summaryの結果← i=5のとき
    b+文字列（data.items[0].summaryの結果← i=6のとき
    ↓
    続く...
    
[/code]

[code]

    function Kansu(){
    
    //GOOGL CALEMDAR APIを使う時に必要なトークン
        var apikey = '個人のAPIキー';
    
    //GOOGL CALEMDARで日付関係の処理
        var now = new Date();
        var y = now.getFullYear();
        var m = now.getMonth() + 1;
        var d = now.getDate();
        var w = now.getDay();
        var wd = ["日", "月", "火", "水", "木", "金", "土"];
        var h = now.getHours();
        var mi = now.getMinutes();
        var s = now.getSeconds();
        var mm = ("0" + m).slice(-2);
        var dd = ("0" + d).slice(-2);
        var hh = ("0" + h).slice(-2);
        var mmi = ("0" + mi).slice(-2);
        var ss = ("0" + s).slice(-2);
    
    //GOOGL CALEMDAR明日の日付
        var dmax = now.getDate() + 1;
        var ddmax = ("0" + dmax).slice(-2);
    
    //GOOGL CALEMDAR今日～明日の日付
        var timeMin = y + "-" + mm + "-" + dd + "T" + hh + ":" + mmi + ":" + ss + "Z";
        var timeMax = y + "-" + mmmax + "-" + dd + "T" + hh + ":" + mmi + ":" + ss + "Z";
    
    
    
    //まずサーバー上のCSVからGoogle Calendarのアドレスを取得
        $.ajax({
            url: 'Google Calendarのアドレスを一覧化した.csv',
            success: function(era) {
            csvListall = $.csv()(era);
    
    //取得したGoogle Calendarのアドレスを１行ずつ総当りでチェック（
        for(var i=0;i<264;i++){
        var calendarId = '';
        var calendarId = csvListall[i][2];
    
    //取得したGoogle Calendarの各アドレスごとにあるランク情報（sss,ss,s,a,b,c）を取得
        var irank = '';
        var irank = csvListall[i][5];
    
    
    
    //$.getJSONにてグーグルカレンダーから情報を取得
            var uri = "https://www.googleapis.com/calendar/v3/calendars/" + calendarId + "/events?key=" + apikey + "&timeMin=" + timeMin + "&timeMax=" + timeMax + "&maxResults=10&orderBy=startTime&singleEvents=true";
            var jsinfo = uri;
                $.getJSON(jsinfo,
                function(data){
                    //取得したsummaryが空じゃない時に実行
                    if (data.items[0].summary != ""){
                    //#imagesに文字列を代入
                        $("#images").append(irank + data.items[0].summary);
                             }
                        });
                    }
                }
        });
    }
    
[/code]

[![画像の説明をここに入力](https://i.stack.imgur.com/m8uFK.png)](https://i.stack.imgur.com/m8uFK.png)


CC BY-SA 3.0
2017-04-06T18:46:53.083
33823
2017-06-13T21:43:47.910
2017-04-06T23:51:52.737
2238
21411
question
javascript json
CSVから読み込んだデータを元にfor文をつかってgooglecalnedarの情報を取得する


`$.getJSON`のコールバック関数`function(data)`で参照している`irank`は別の関数`function(era)`で定義されています。このため、`irank`の状態は`function(era)`が一回実行されるごとに1個確保されます。  
一方`$.getJSON`はコールバック呼び出しを非同期に呼び出します。ですので`function(era)`で`$.getJSON`が264回呼び出された後に`function(data)`が264回実行され、`irank`の値はすべて264番目の状態となります。

`function(data)`を例えば以下のように書き換えると各呼び出し時の`irank`が保存されるようになるかと思います。

[code]

    (function(irank){
        return function(data) {
            // …
        };
    })(irank)
    
[/code]


CC BY-SA 3.0
2017-04-06T23:48:50.760
33825
2017-04-06T23:48:50.760
5750
33823
answer


原因はpgrhoさんが書かれている通りです。

いつかあなたが絶対に引っかかる、ある一つのJavaScriptの罠  
<http://qiita.com/ukiuni@github/items/463493a690265cec8bb7>

別解としてfor文を使用せずに、[`jQuery.each()`](http://api.jquery.com/jQuery.each/)や[`Array.prototype.forEach()`](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach)で配列内(csvListall)の値を1つずつ処理する方法もあります。

`Array.prototype.slice(0,
264)`で最初の要素から264個だけ処理するようにしていますが、csvListallの要素すべてに対して処理を行うのであれば、このメソッドは不要なので削除してください。

**jQuery.each():**

[code]

    $.ajax({
        url: 'Google Calendarのアドレスを一覧化した.csv',
        success: function (era) {
            csvListall = $.csv()(era);
    
            //取得したGoogle Calendarのアドレスを１行ずつ総当りでチェック
            $.each(csvListall.slice(0, 264), function(index, value){
                var calendarId = value[2];
    
                //取得したGoogle Calendarの各アドレスごとにあるランク情報（sss,ss,s,a,b,c）を取得
                var irank = value[5];
    
                //...
    
            });
        }
    });
    
[/code]

**Array.prototype.forEach():**

[code]

    $.ajax({
        url: 'Google Calendarのアドレスを一覧化した.csv',
        success: function (era) {
            csvListall = $.csv()(era);
    
            //取得したGoogle Calendarのアドレスを１行ずつ総当りでチェック
            csvListall
                .slice(0, 264)
                .forEach(function(value, index){
                    var calendarId = value[2];
    
                    //取得したGoogle Calendarの各アドレスごとにあるランク情報（sss,ss,s,a,b,c）を取得
                    var irank = value[5];
    
                    //...
    
                });
        }
    });
    
[/code]


CC BY-SA 3.0
2017-04-07T04:12:22.287
33831
2017-04-07T04:12:22.287
3068
33823
answer