Deep Insider の Tutor コーナー
>>  Deep Insider は本サイトからスピンオフした姉妹サイトです。よろしく! 
AngularJS TIPS

AngularJS TIPS

JSON形式のWeb APIにアクセスするには?($http)

2015年12月21日

Web APIと通信する際に問題となるクロスドメイン制約を回避するために使われるテクニック「JSONP」を、AngularJSで実現するための基本的な方法を説明する。

  • このエントリーをはてなブックマークに追加

 XMLHttpRequest(XHR)オブジェクトのよく知られた制約として、クロスドメイン制約があります。クロスドメイン制約とは、(デフォルトでは)JavaScriptからドメインを超えて通信できない制約のことです。$httpサービスもまた、内部的にはXHRオブジェクトを利用していますので、この制約からは自由ではありません。

 クロスドメイン制約を回避するテクニックにはさまざまなものがありますが、その中でも古典的で、よく利用されているのがJSONP(JSON with Padding)です。JSONPとは、その名の通り、JSON(=JavaScriptのオブジェクトリテラル形式になぞらえたデータ)でデータを交換する仕組みのこと。内部的にもXHRオブジェクトを利用しませんので、クロスドメイン制約からも自由です。

 そして、$httpサービスでもjsonpメソッド(またはmethodパラメーターにjsonp)を利用することで、JSONPをごくシンプルな手順で利用できます。本稿では、「OpenWeatherMap」で提供されるWeb APIを利用して、指定された都市の現在の天気を表示してみます。まずは、具体的なコードを見てみましょう。

HTML
<!DOCTYPE html>
<html ng-app="myApp">
<head>
<meta charset="UTF-8" />
<title>AngularJS TIPS</title>
</head>
<body ng-controller="MyController">
<form>
  <select ng-model="city">
    <option value="1850147">東京</option>
    <option value="1856057">名古屋</option>
    <option value="1853909">大阪</option>
    <option value="1907125">福岡</option>
  </select>
  <button ng-click="onclick()">検索</button>
</form>
<img ng-src="{{weather}}" />
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.7/angular.min.js"></script>
<script>
angular.module('myApp', [])
  .controller('MyController', ['$scope', '$http', function($scope, $http) {
    $scope.onclick = function() {
      $http.jsonp('http://api.openweathermap.org/data/2.5/weather',
        {
          params: {
            callback: 'JSON_CALLBACK',  // 1コールバック関数の名前
            id: $scope.city,            // 都市コード
            APPID: 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'  // アプリケーションキー
          }
        }
      )
      // 2Web APIの結果に基づいて天気アイコンを表示
      .success(function(data) {
        $scope.weather = 'http://openweathermap.org/img/w/'
          + data.weather[0].icon +'.png';
      })
      .error(function(err) {
        console.log(err);
      });
    };
  }]);
</script>
</body>
</html>
JSONPを利用してWeb APIにアクセスするためのコード(jsonp.html)
指定された都市の現在の天気をアイコン表示
指定された都市の現在の天気をアイコン表示

 $http.jsonpメソッドの構文それ自体は、別稿「TIPS:サーバーサイドと非同期通信するには?」で解説した$httpサービスと同様です。ここでポイントとなるのは2点です。

1コールバック関数の名前は「JSON_CALLBACK」

 jsonpメソッドでは、パラメーター(paramscallbackパラメーター)としてコールバック関数の名前を指定しなければなりません。この場合、コールバック関数とは、Web APIから応答を得られた時に内部的に呼び出される関数のことです。関数名は固定で「JSON_CALLBACK」とします。

[Note]OpenWeatherMapのその他のパラメーター

 paramsパラメーターに渡している、その他のパラメーターは、「OpenWeatherMap」固有のパラメーターです。

  • id: 都市コードを表します。利用できる都市コードは、こちらからダウンロードできます。
  • APPID: APIを利用するためのキーです。「OpenWeatherMap」からアカウントを作成することで取得できます。

 実際にサンプルを動作するに際しては、自分で取得したコードに置き換えてください。

 まずは、この2個が主となりますので、その他に利用できるパラメーターについては、「Current weather data」から確認してください。

2成功コールバック関数の引数に渡されるのはJavaScriptオブジェクト

 成功コールバック関数の引数data(=結果)には、デコード済みのJavaScriptオブジェクトが渡されます。JSON文字列ではありませんので、angular.fromJSONメソッドなどによるデコード処理は不要です。

 オブジェクトの構造は、もちろん、Web APIによって異なります。例えば、「OpenWeatherMap」であれば、以下のようなオブジェクトを返します(主なものを抜粋しています)。

 /
name …… 地名
coord
  lon …… 経度
  lat …… 緯度
sys
  country …… 国コード
  sunrise …… 日の出時間
  sunset …… 日の入り時間
weather(配列)
  main …… 天気
  icon …… 天気を表すアイコン
main
  temp …… 気温
  humidity …… 湿度
  pressure …… 気圧
  temp_min …… 最低気温
  temp_max …… 最高気温
wind
  speed …… 風速
  deg …… 風向き
rain
  "3h …… 直近3時間の降水量
「OpenWeatherMap」で返されるJavaScriptオブジェクトの構造(主なものを抜粋)

 ここでは、data.weather[0].iconで天気を表すアイコン(ベース名)を取得し、これをもとに<img>要素に反映させることで、指定された都市の天気を画像表示しています。

処理対象:非同期通信 カテゴリ:サービス
API:$http カテゴリ:ng(コアモジュール) > service(サービス)

※以下では、本稿の前後を合わせて5回分(第35回~第39回)のみ表示しています。
 連載の全タイトルを参照するには、[この記事の連載 INDEX]を参照してください。

AngularJS TIPS
35. サーバーサイドと非同期通信するには?($http)

AngularJSでサーバーサイドのWeb APIと非同期通信する方法を説明。また、ログの種類や、ショートカットメソッドについても紹介する。

AngularJS TIPS
36. サーバーサイドとHTTP POSTで非同期通信するには?($http)

AngularJSでHTTP POSTで非同期通信する方法を説明。また、送信データをJSONではなくjQuery形式にする方法や、PHPでJSONデータをデコードする方法も紹介する。

AngularJS TIPS
37. 【現在、表示中】≫ JSON形式のWeb APIにアクセスするには?($http)

Web APIと通信する際に問題となるクロスドメイン制約を回避するために使われるテクニック「JSONP」を、AngularJSで実現するための基本的な方法を説明する。

AngularJS TIPS
38. 指定された時間の経過で処理を実行するには?($interval/$timeout)

ミリ秒単位で処理を実行できる、いわゆる「タイマー」である$intervalサービスの基本的な使い方を解説。また、一定時間後に処理を実行する$timeoutサービスについても説明する。

AngularJS TIPS
39. 配列/オブジェクトの内容を列挙するには?(forEach)

angular.forEachメソッドを使って、配列の要素やオブジェクトのメンバーを列挙する方法を解説する。

サイトからのお知らせ

Twitterでつぶやこう!