Top / AngularJS / TIPS集

RESTのデータをキャッシュする

一度RESTでとったデータをキャッシュしておく方法について。

angular.module('uiRouterSampleApp')
  .controller('Menu6Ctrl', function (sampleRestService, $scope) {
    // 同期っぽく、値をセットする
    var result = sampleRestService.getWeather();
    console.log(result);


    // 非同期っぽく、callbackで値をセットする
    sampleRestService.getWeather().$promise.then(function (data) {
      $scope.result = data;
      console.log(data);
    });
  })
  .factory('sharedService', function () {
    // Public API here
    return {
      isEmpty: function () {
        return this._data1 == null;
      },

      get cacheData() {
        console.log('getter!!');
        return this._data1;
      },
      set cacheData(val) {
        console.log('setter!!');
        this._data1 = val;
      }
    };
  })
  .factory('sampleRestService', function ($resource, sharedService) {
    // Public API here
    return {
      getWeather: function () {
        if (!sharedService.isEmpty()) {
          console.log('キャッシュから返す');
          return sharedService.cacheData;
        } else {
          console.log('サーバからとって返す.そのときキャッシュにも詰める');
          return $resource("/api/weather1.json").get(function (result) {
            sharedService.cacheData = result;
          });
        }
      }
    };
  });

こんな感じで、実行結果を保持しておいて次回以降それを返すなんて事ができそうです。

HTTPの通信エラーを一網打尽に対応する

angular
   .module("hoge", [])
   .config(['$httpProvider', function ($httpProvider) {
       $httpProvider.interceptors.push(
           ['$q', '$timeout', '$window', function ($q, $timeout, $window) {
               return {
                   responseError: function (rejection) {
                       var message = '';
                       if (400 == rejection.status) {
                           message = '不正なリクエスト';
                       }
                       if (401 == rejection.status) {
                           message = '認証エラーです。';
                       }
                       if (404 == rejection.status) {
                           message = 'そのリソースは存在しません';
                       }
                       if (405 == rejection.status) {
                           message = 'そのリクエストは許可されていません。';
                       }
                       if (409 == rejection.status) {
                           message = '登録しようとしたリソースはすでに存在するようです。';
                       }
                       if (500 == rejection.status) {
                           message = '予期しないエラーが発生しました。';
                       }
                       $timeout(function () {
                           $window.alert(message + ": [" + rejection.status + "]");
                       })
                       return $q.reject(rejection);
                   }
               };
           }]
       );
   }]);

クエリパラメタから値を取り出す

/xxx/xxx.html?key=hogehoge

ってURLで画面を表示したときに、

var key = $location.search()["key"];

hogehogeが取得できます。

getter/setterでフィールドにアクセスする

JavaBeans?みたいに。。

angular.module(APP_NAME)
  .factory('getsetservice', function () {
    // Public API here
    return {
      get data1() {
        console.log('getter!!');
        return this._data1;
      },
      set data1(val) {
        console.log('setter!!');
        this._data1 = val;
      }
    };
  });

Controller側はこちら;

angular.module(APP_NAME)
  .controller('Menu5Ctrl', function ($scope, getsetservice) {
       getsetservice.data1 = 'kino';
       console.log('data1: ' + getsetservice.data1);
       console.log('_data1: ' + getsetservice._data1);    <- これでアクセスできちゃうのはご愛敬 :-)
    }
  });

プロパティに直接セットしているように見えるけど実はアクセッサ経由。。ストア先をメモリ上でなくてlocalStorageに変更しよう、とかなっても利用側は変更不要にできそうですね。。

保存先をWebStorage?に変更してみた

 angular.module(APP_NAME)
  .factory('getsetservice', function ($localStorage, $sessionStorage) {
    // Public API here
    return {
      get localData1() {
        console.log('local storage getter!!');
        return $localStorage._localData1;
      },
      set localData1(val) {
        console.log('local storage setter!!');
        $localStorage._localData1 = val;
      },
      get sessionData1() {
        console.log('session storage getter!!');
        return $sessionStorage._sessionData1;
      },
      set sessionData1(val) {
        console.log('session storage setter!!');
        $sessionStorage._sessionData1 = val;
      }
    };
  });

こうしておけば、ストア先をWebStorage?(session/localどちらでも) にすることができます。

あ、AngularJSWebStorage?を使う場合は

bower install ngstorage --save

でngstorageをインストールし、

angular.module(APP_NAME, [
   ..... 
   'ui.router',
   'ngStorage'
 ]);

でngStorageを依存モジュールに定義しておきます

ControllerからWebStorage?をつかう

angular.module(APP_NAME)
  .controller('Menu5Ctrl', function ($scope, $localStorage, $sessionStorage) {
    // デフォルト値とともに変数の定義
    $scope.$storage1 = $localStorage.$default({
      ctrl_localData2: 'localDef'
    });
    $scope.$storage2 = $sessionStorage.$default({
      ctrl_sessionData2: 'sessionDef'
    });

    $scope.onClick = function () {
      $scope.$storage1.ctrl_localData2 = $scope.localData1;
      $scope.$storage2.ctrl_sessionData2 = $scope.sessionData1;
    }
  });

ng-modelで紐付けたオブジェクトの構造

たとえば以下のように ng-modelでオブジェクトをバインドした場合

<form class="form-horizontal" role="form" ng-submit="addRow()">
    <div class="form-group">
        <label class="col-md-2 control-label">param1</label>
        <div class="col-md-4">
            <input type="text" class="form-control" name="postData.param1"
                   ng-model="postData.param1" />
        </div>
    </div>
    <div class="form-group">
        <label class="col-md-2 control-label">param2</label>
        <div class="col-md-4">
            <input type="text" class="form-control" name="postData.param2"
                   ng-model="postData.param2" />
        </div>
    </div>
    <div class="form-group">
        <div style="padding-left:110px">
            <input type="submit" value="Submit" class="btn btn-primary"/>
        </div>
    </div>
</form>

$scope.postDataは

{
  param1="aaa",
  param2="bbbbb"
}

のようなオブジェクトが格納されます。$httpとかに

$http({
  method: method,
  url: url,
  data: postData  ←ココ
});

こんな感じでそのまま渡せてとても便利。。

YeomanでAngularJSの Scaffoldをつくる

sudo npm install -g yo bower grunt-cli
sudo npm install -g generator-angular
sudo npm install -g generator-karma karma

がインストール済みだとして、

yo angular

でOK

YeomanでServiceを追加する

yo angular:factory weatherService

weatherservice.jsに weatherServiceというfactoryが追加され、さらにindex.htmlに

<script src="scripts/services/weatherservices.js"></script>

が自動挿入されます。

YeomanでControllerを追加する

yo angular:controller menu5

menu5.jsに Menu5CtrlというControllerが追加され、さらにindex.htmlに

<script src="scripts/controllers/menu5.js"></script>

が自動挿入されます。

関連リンク


この記事は

選択肢 投票
おもしろかった 1  
そうでもない 0  

Top / AngularJS / TIPS集

現在のアクセス:4010


トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2021-12-14 (火) 11:32:31 (857d)