AngularJSでの非同期処理の話

9,025 views

Published on

Published in: Technology
0 Comments
14 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
9,025
On SlideShare
0
From Embeds
0
Number of Embeds
370
Actions
Shares
0
Downloads
22
Comments
0
Likes
14
Embeds 0
No embeds

No notes for slide

AngularJSでの非同期処理の話

  1. 1. 2014年6月8日 AngularJSでの非同期処理の話 AngularJS 勉強会 by GDG神戸
  2. 2. 自己紹介 ✤ おのうえ (@_likr)! ✤ 博士課程の大学院生! ✤ 可視化や最適化を使った意思決定支援に興味あり
  3. 3. Webと可視化 ✤ Canvas、SVG、WebGLといったAPI、
 D3.js、Three.jsといったライブラリによって
 Web上での可視化基盤が整えられた http://threejs.org/http://d3js.org/
  4. 4. AngularJSでやってること
  5. 5. 本セッションの内容 ✤ JavaScriptには、HTTPアクセス、ファイルIO、
 アニメーションなど非同期処理がたくさん! ✤ 可視化のためのデータ取得も非同期処理!! ✤ 実アプリケーションには必要不可欠な非同期処理を
 AngularJSでどのように扱うのか様々な例を紹介
  6. 6. 目次 1. 遅延処理 - $timeout! 2. HTTPアクセス - $http! 3. REST APIサーバーへのアクセス - ngResource! 4. Promiseを提供する - $q! 5. ngRouteとresolve
  7. 7. 目次 1. 遅延処理 - $timeout! 2. HTTPアクセス - $http! 3. REST APIサーバーへのアクセス - ngResource! 4. Promiseを提供する - $q! 5. ngRouteとresolve
  8. 8. $timeout ✤ window.setTimeoutのラッパー! ✤ 指定した時間待った後処理を実行する! ✤ 使い方 https://docs.angularjs.org/api/ng/service/$timeout $timeout(fn[, delay]) fn delay 遅れさせる時間(ミリ秒) 実行する処理
  9. 9. $timeoutのサンプル <div ng-app> <div ng-controller="TimeoutExample"> <span>{{str}}</span> <button ng-click="cancel()">Cancel</button> </div> </div> function TimeoutExample($scope, $timeout) { $scope.str = 'Prompt Result'; var promise = $timeout(function() { $scope.str = prompt('Input Message'); }, 2000); $scope.cancel = function() { $timeout.cancel(promise); $scope.str = 'Canceled'; }; } http://jsfiddle.net/likr/2NMyP/ $timeoutで、2秒後にプロンプトを
 表示して、入力をビューに表示する $timeout.cancelに$timeoutの
 戻り値を渡すことで処理の中止 $timeoutを依存性注入する
  10. 10. setTimeoutじゃダメなの? function TimeoutExample($scope) { $scope.str = 'Prompt Result'; ! var timeoutId = setTimeout(function () { $scope.str = prompt('Input Message'); }, 2000); ! $scope.cancel = function () { clearTimeout(timeoutId); $scope.str = 'Canceled'; }; } http://jsfiddle.net/likr/243ja/
  11. 11. setTimeoutじゃダメなの? function TimeoutExample($scope) { $scope.str = 'Prompt Result'; ! var timeoutId = setTimeout(function () { $scope.str = prompt('Input Message'); }, 2000); ! $scope.cancel = function () { clearTimeout(timeoutId); $scope.str = 'Canceled'; }; } http://jsfiddle.net/likr/243ja/ function TimeoutExample($scope) { $scope.str = 'Prompt Result'; ! var timeoutId = setTimeout(function () { $scope.$apply(function () { $scope.str = prompt('Input Message'); }); }, 2000); ! $scope.cancel = function () { clearTimeout(timeoutId); $scope.str = 'Canceled'; }; } データバインドを反映させるために$scope.$applyが必要 http://jsfiddle.net/likr/243ja/2/
  12. 12. $timeoutとpromise ✤ Promise: 非同期処理をうまく扱うためのインタフェース! ! ! ! ! ✤ $timeoutはpromiseを返す promise.catch(onRejected) onFullfilled onRejected 処理が失敗したときの処理 処理が成功した時の処理 promise.then(onFullfilled[, onRejected])
  13. 13. $timeoutとpromiseのサンプル function TimeoutExample($scope, $timeout) { $scope.str = 'Prompt Result'; $scope.status = 'Pending'; ! var promise = $timeout(function () { $scope.str = prompt('Input Message'); }, 2000); ! promise.then(function () { $scope.status = 'Fullfilled'; }); promise.catch(function () { $scope.status = 'Rejected'; }); ! $scope.cancel = function () { $timeout.cancel(promise); $scope.str = 'Canceled'; }; } http://jsfiddle.net/likr/2NMyP/1/ $timeoutのpromiseに成功時、
 失敗時のコールバックを登録
  14. 14. 目次 1. 遅延処理 - $timeout! 2. HTTPアクセス - $http! 3. REST APIサーバーへのアクセス - ngResource! 4. Promiseを提供する - $q! 5. ngRouteとresolve
  15. 15. $http ✤ HTTPサーバーへとの通信を行う! ✤ GET / POST / PUT / DELETE / HEAD! ✤ JSONP! ✤ 使い方 https://docs.angularjs.org/api/ng/service/$http $http.get(url[, config]) $http.post(url[, config]) … $http(config)
  16. 16. $httpのサンプル function HttpExample($scope, $http) { $http.get('http://example.com/') .then(function(response) { $scope.data = response.data; }); } http://jsfiddle.net/likr/ct6Jn/ function HttpExample($scope, $http) { $http({ method: 'get', url: 'http://example.com/' }).then(function(response) { $scope.data = response.data; }); } methodとurlを指定して$httpを呼び出す $httpを依存性注入する $httpはPromiseを返すのでthenで! 通信成功、失敗時の処理ができる $http.getは$httpのショートカット
  17. 17. Response ✤ Promiseでresolveされるオブジェクトのプロパティ! ✤ data: Responseのbody! ✤ status: HTTPのステータスコード! ✤ headers: HTTPヘッダーのgetter! ✤ config: $httpの引数! ✤ statusText: HTTPのステータス文章
  18. 18. HttpPromise ✤ HttpPromise! ✤ $httpが返すPromise! ✤ thenの代わりにsuccessとerrorが使える function HttpExample($scope, $http) { $http.get('http://gdgkobe-ng-guestbook.appspot.com/greetings') .success(function(response) { $scope.data = response.data; }) .error(function(reason) { }); }
  19. 19. 他のAJAX APIと比べて ✤ $scope.$applyの問題がない! ✤ $httpBackendによるテストが容易
  20. 20. 目次 1. 遅延処理 - $timeout! 2. HTTPアクセス - $http! 3. REST APIサーバーへのアクセス - ngResource! 4. Promiseを提供する - $q! 5. ngRouteとresolve
  21. 21. ngResource ✤ REST APIサーバーとの通信を便利にするモジュール! ✤ REST APIサーバーの例 https://docs.angularjs.org/api/ngResource Method URL 処理 GET http://example.com/greetings greeting GET http://example.com/greetings/1 ID1 POST http://example.com/greetings 新しい PUT http://example.com/greetings/1 ID1 DELETE http://example.com/greetings/1 ID1
  22. 22. ngResourceの利用 ✤ AngularJS本体とは別jsファイルで提供されているので
 scriptタグを追加して読み込む! ! ✤ 依存モジュールとして指定 <script src="angular-resource.js"></script> var app = angular.module('example', ['ngResource']);
  23. 23. Resourceの作成 ✤ リソースのURLを指定してResourceを作成! ! ✤ factoryでserviceとして登録しておくと便利 $resource(‘http://example.com/greetings/:id') app.factory('Greeting', function($resource) { return $resource(‘http://example.com/greetings/:id'); });
  24. 24. Resourceの利用 ✤ データ取得! ! ! ✤ データ保存 var Greeting = $resource('http://example.com/greetings/:id'); ! var greetings = Greeting.query(); var newGreeting = new Greeting(); newGreeting.content = 'hello'; newGreeting.$save();
  25. 25. Resourceの遅延処理 var app = angular.module('example', ['ngResource']); ! app.factory('Greeting', function($resource) { return $resource('http://gdgkobe-ng-guestbook.appsp }); ! app.controller('Main', function(Greeting) { var greetings = Greeting.query(); greetings.$promise .then(function() { console.log(greetings); }); console.log(greetings); }); Resourceのメソッドはプレースホルダーを
 返して、処理が完了した時点で内容を挿入する http://jsfiddle.net/likr/BHS5v/
  26. 26. ResourceとPromise ✤ 関数の結果の$promiseプロパティでPromiseを取得
 get()、query()、delete()、$save… Greeting.query().$promise .then(function(greetings) { // TODO });
  27. 27. 目次 1. 遅延処理 - $timeout! 2. HTTPアクセス - $http! 3. REST APIサーバーへのアクセス - ngResource! 4. Promiseを提供する - $q! 5. ngRouteとresolve
  28. 28. Promiseを提供する ✤ $timeout、$http、ngResourceはプロミスで
 非同期処理を扱うことができる! ✤ 自分の非同期処理、非AngularJSの外部ライブラリを
 同様のAPIで提供する方法は?
  29. 29. $q ✤ Promiseの作成、ラップをする! ✤ $timeout、$http、ngResource内でも使用されている https://docs.angularjs.org/api/ng/service/$q $q.defer() $q.when(promise) $q.all(promises)
  30. 30. $q.defer ✤ Deferredオブジェクトを作成する! ! ✤ resolve、reject、notifyで非同期処理の状態を通知する! ! ! ✤ promiseプロパティでPromiseオブジェクトを取得する deferred.resolve(value) deferred.reject(reason) deferred.notify(value) var deferred = $q.defer() var promise = deferred.promise;
  31. 31. $qのサンプル1 var app = angular.module('q-example', []); ! app.factory('d3get', function($q) { return function(xhr) { var deferred = $q.defer(); xhr .on('load', function(data) { deferred.resolve(data); }) .on('error', function(status) { deferred.reject(status); }) .get(); return deferred.promise; }; }) ! app.controller('Main', function(d3get) { d3get(d3.csv('http://example.com/data.csv')) .then(function(data) { // TODO }); }); D3.jsのxhr系関数をラップしてみる $q.deferでdeferredオブジェクトを作成 データ取得が成功したらresolve promiseオブジェクトを返す thenでデータ取得後の処理を行う loadDataをラップした関数をfactoryで提供 データ取得が失敗したらreject
  32. 32. $qのサンプル2 function getData(url) { return $.get(url); } ! ! function Main($q) { $q.when(getData('http://example.com/')) .then(function(data) { // TODO }); }); jQueryのAJAX関数をラップしてみる AngularJSとは関係のない、 jQueryXHR(Promise)を返す関数 $q.whenでラップすると! $scope.$applyの手間等が不要
  33. 33. 目次 1. 遅延処理 - $timeout! 2. HTTPアクセス - $http! 3. REST APIサーバーへのアクセス - ngResource! 4. Promiseを提供する - $q! 5. ngRouteとresolve
  34. 34. 問題 ✤ 非同期処理が成功してからコントローラーの処理をし たい場合! ✤ 認証、データ取得
  35. 35. ngRoute ✤ AngularJSのルーティングモジュール! ✤ コントローラーへの依存性注入で、コントローラー処 理に入る前にデータ取得などを済ませることができる! ✤ ui-routerでも同様 https://docs.angularjs.org/api/ngRoute
  36. 36. ngRouteのresolve var app = angular.module('resolve-example', ['ngRoute']); ! app.config(function($routeProvider) { $routeProvider.when('/', { template: '{{data}}', controller: function($scope, response) { $scope.data = response.data; }, resolve: { response: function($http) { return $http.get('http://example.com/'); } } }); }); resolveの要素がPromiseを返した場合、 全てのPromiseがresolveされてからコン トローラーの処理を行う
  37. 37. まとめ ✤ AngularJSが提供する非同期処理APIを使うことで
 複雑な非同期処理も簡単に扱える! ✤ Promiseパターンで非同期処理を統一的に扱える! ✤ $qで自分で非同期処理を提供できる! ✤ AngularJS用じゃない非同期処理は、データバインド に気をつける($q.when, $scope.$apply)

×