QA@IT

Angularjs $httpサービス内のdataで得た変数を使いたい

3101 PV

Angularjs 初心者です。
正誤を表示するテーブルを作っています。そのテーブル内でデータベースと通信して、得た内容(1か0)、によって動的に中身を変えたいのですがうまくいきません。.success内で変数を定義して、外で使いたいのですが、undefinedとなって使えません。
json形式が関係しているのでしょうか?

アドバイスいただけると幸いです。

var tbl ="";

tbl += "<table><tr>";

for (var i=1;i<=4;i++){

      $http({
              method:'GET',
              url: 'http://www.XXXXX.jp/table.php',
              params:{id:$localStorage.Id}
              })
              .success(function(data,status,headers,config){
                 var flag = data; 
                 //////ここでconsole.logにflagを表示させると1か0は返ってきています。
              });

if($flag == 1){/////////////ここで$flag がundefined となります。
    var hoge = "OK";
} else {
    var hoge = "NG";
}

tbl += "<td>" + hoge + "</td>";

}


}
tbl += "</tr></table>";

回答

$httpサービスは非同期リクエストなので、for文の中に書いてもその最中には実施されません。
構成から考え直す必要があります。

簡単に言えば上から順には実行されていないということです。
.successのコールバックの中、$http({の前の行、tbl += "</tr></table>";の次の行でconsole.logを出力してみるとわかると思います。

jQueryの様な組み立て方になっている印象です、
angularで書くなら4つのアイテムそれぞれをdirectiveにしてしまうか、promiseを連鎖なりreduceでループさせるか、
配列をモデルにしておいて$scope.$apply使うかといった手が考えられますが、
コードも断片的なため他の構成がどうなっているのかもわかりませんし、
初心者とのことですから説明してもまだわからないと思います。

まずは$httpの動きなどを学ばれるとよいでしょう。jQueryの$getでも構いません。
外の変数の値を利用するなら、レキシカルスコープも知らないといけません。

今できる範囲では $httpをネストして呼ぶ形にすれば実現はできるでしょう。
そのままではきれいではないので、そのうえで改良するとか別の方法を考えるといいかもしれません。

  // 長くなるので2つだけ。
  var flag1 = 0, flag2 = 0;

  $http({
    method:'GET',
    url: 'http://www.XXXXX.jp/table.php',
    params:{id:$localStorage.Id}
    })
    .success(function(data,status,headers,config){
      var flag1 = data; 

      $http({
        /* 同じみたいなので省略 */
        })
        .success(function(data,status,headers,config){
          var flag2 = data; 

          var tbl ="";
          tbl += "<table><tr>";
          tbl += "<td>"+(flag1 == 1?"OK":"NG")+"</td>";
          tbl += "<td>"+(flag2 == 1?"OK":"NG")+"</td>";
          tbl += "</tr></table>";        
          console.log(tbl);

          // またはあらかじめデータバインドしておいて(`<pre>{{flag1}} - {{flag2}}</pre>`等)
          // $scope.flag1 = flag1; $scope.flag2 = flag2; $scope.$apply();
          // だといくらかangularらしくなると思います。

        });
    });

バインド使う場合は、ネストしなくても動作はしますが振る舞いが異なります(特に量が増えると顕著に)。
各successでconsole.logしてみて違いを確認してみてください。

編集 履歴 (0)
  • ご回答ありがとうございます。とても親切にわかりやすく教えていただき幸いです。やはりforの中では動かないのですね。よくわかりました。
    もっと勉強してみようと思います。
    ありがとうございました。
    -

.successで変数を定義されているので、flagのスコープを意識する必要があります。外で使いたいのならば、returnするか、外で定義した変数に代入するといいと思います。

あるいは、「if($flag == 1){」の「$」を取るとどうなりますか?

編集 履歴 (0)
  • ご回答ありがとうございます。$flagの部分はミスタイプです。flagでした。
    アドバイスありがとうございます。試してみます。
    -
ウォッチ

この質問への回答やコメントをメールでお知らせします。