AngularJSでの非同期処理の話

  • 2,868 views
Uploaded on

 

More in: Technology
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Be the first to comment
No Downloads

Views

Total Views
2,868
On Slideshare
0
From Embeds
0
Number of Embeds
4

Actions

Shares
Downloads
10
Comments
0
Likes
6

Embeds 0

No embeds

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
    No notes for slide

Transcript

  • 1. 2014年6月8日 AngularJSでの非同期処理の話 AngularJS 勉強会 by GDG神戸
  • 2. 自己紹介 ✤ おのうえ (@_likr)! ✤ 博士課程の大学院生! ✤ 可視化や最適化を使った意思決定支援に興味あり
  • 3. Webと可視化 ✤ Canvas、SVG、WebGLといったAPI、
 D3.js、Three.jsといったライブラリによって
 Web上での可視化基盤が整えられた http://threejs.org/http://d3js.org/
  • 4. AngularJSでやってること
  • 5. 本セッションの内容 ✤ JavaScriptには、HTTPアクセス、ファイルIO、
 アニメーションなど非同期処理がたくさん! ✤ 可視化のためのデータ取得も非同期処理!! ✤ 実アプリケーションには必要不可欠な非同期処理を
 AngularJSでどのように扱うのか様々な例を紹介
  • 6. 目次 1. 遅延処理 - $timeout! 2. HTTPアクセス - $http! 3. REST APIサーバーへのアクセス - ngResource! 4. Promiseを提供する - $q! 5. ngRouteとresolve
  • 7. 目次 1. 遅延処理 - $timeout! 2. HTTPアクセス - $http! 3. REST APIサーバーへのアクセス - ngResource! 4. Promiseを提供する - $q! 5. ngRouteとresolve
  • 8. $timeout ✤ window.setTimeoutのラッパー! ✤ 指定した時間待った後処理を実行する! ✤ 使い方 https://docs.angularjs.org/api/ng/service/$timeout $timeout(fn[, delay]) fn delay 遅れさせる時間(ミリ秒) 実行する処理
  • 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. 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. 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. $timeoutとpromise ✤ Promise: 非同期処理をうまく扱うためのインタフェース! ! ! ! ! ✤ $timeoutはpromiseを返す promise.catch(onRejected) onFullfilled onRejected 処理が失敗したときの処理 処理が成功した時の処理 promise.then(onFullfilled[, onRejected])
  • 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. 目次 1. 遅延処理 - $timeout! 2. HTTPアクセス - $http! 3. REST APIサーバーへのアクセス - ngResource! 4. Promiseを提供する - $q! 5. ngRouteとresolve
  • 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. $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. Response ✤ Promiseでresolveされるオブジェクトのプロパティ! ✤ data: Responseのbody! ✤ status: HTTPのステータスコード! ✤ headers: HTTPヘッダーのgetter! ✤ config: $httpの引数! ✤ statusText: HTTPのステータス文章
  • 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. 他のAJAX APIと比べて ✤ $scope.$applyの問題がない! ✤ $httpBackendによるテストが容易
  • 20. 目次 1. 遅延処理 - $timeout! 2. HTTPアクセス - $http! 3. REST APIサーバーへのアクセス - ngResource! 4. Promiseを提供する - $q! 5. ngRouteとresolve
  • 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. ngResourceの利用 ✤ AngularJS本体とは別jsファイルで提供されているので
 scriptタグを追加して読み込む! ! ✤ 依存モジュールとして指定 <script src="angular-resource.js"></script> var app = angular.module('example', ['ngResource']);
  • 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. Resourceの利用 ✤ データ取得! ! ! ✤ データ保存 var Greeting = $resource('http://example.com/greetings/:id'); ! var greetings = Greeting.query(); var newGreeting = new Greeting(); newGreeting.content = 'hello'; newGreeting.$save();
  • 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. ResourceとPromise ✤ 関数の結果の$promiseプロパティでPromiseを取得
 get()、query()、delete()、$save… Greeting.query().$promise .then(function(greetings) { // TODO });
  • 27. 目次 1. 遅延処理 - $timeout! 2. HTTPアクセス - $http! 3. REST APIサーバーへのアクセス - ngResource! 4. Promiseを提供する - $q! 5. ngRouteとresolve
  • 28. Promiseを提供する ✤ $timeout、$http、ngResourceはプロミスで
 非同期処理を扱うことができる! ✤ 自分の非同期処理、非AngularJSの外部ライブラリを
 同様のAPIで提供する方法は?
  • 29. $q ✤ Promiseの作成、ラップをする! ✤ $timeout、$http、ngResource内でも使用されている https://docs.angularjs.org/api/ng/service/$q $q.defer() $q.when(promise) $q.all(promises)
  • 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. $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. $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. 目次 1. 遅延処理 - $timeout! 2. HTTPアクセス - $http! 3. REST APIサーバーへのアクセス - ngResource! 4. Promiseを提供する - $q! 5. ngRouteとresolve
  • 34. 問題 ✤ 非同期処理が成功してからコントローラーの処理をし たい場合! ✤ 認証、データ取得
  • 35. ngRoute ✤ AngularJSのルーティングモジュール! ✤ コントローラーへの依存性注入で、コントローラー処 理に入る前にデータ取得などを済ませることができる! ✤ ui-routerでも同様 https://docs.angularjs.org/api/ngRoute
  • 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. まとめ ✤ AngularJSが提供する非同期処理APIを使うことで
 複雑な非同期処理も簡単に扱える! ✤ Promiseパターンで非同期処理を統一的に扱える! ✤ $qで自分で非同期処理を提供できる! ✤ AngularJS用じゃない非同期処理は、データバインド に気をつける($q.when, $scope.$apply)