#실행결과 http://study.jeju.onl/ch20/ajax.html
이장에서는 Ajax 기능을 활용하기 위한 $http와 프로미스 제어를 위한 $q에 대해서 설명하고 있다. 두 서비스는 Ajax의 비동기적 실행을 제어하기 위해 필수적인 기능이다. 이를 이용하여 REST 서비스를 구현할 수 있다.
주 내용은 다음과 같다.
- Ajax 요청 수행
– $http 의존성 선언, $http.get().success() 기능 정의
– $http 메서드: get(), post(), delete(), put(), head(), jsonp()
– Ajax 응답 수신: success(), error(), then( successFn(), errorFn() )
– 응답정보 상세 조회: data, status, headers, config - Ajax 요청 설정
– $http의 설정 속성: data, headers, method, params, timeout, transformRequest, transformResponse, withCredentials, xsrfHeaderNamesrf, CookieName
– 응답 변형: transformResponse
– 요청 변형: transformRequest
– Ajax 기본값 설정: defaults 속성그룹
– Ajax 인터셉터 활용: 요청 전과 응답 후에 기능 정의
$httpProvider.interceptors - 프로미스 활용
– $q 메서드: all(promises), defer(), reject(reason), when(value)
– 지연객체 defer()의 메서드: resolve(result), reject(reason), notify(result), promise
– 프로미스 처리: then( success, error, notify), catch(error), finally(fn)
– 프로미스와 이벤트의 차이점
1) 한번만 사용하고 버려짐. 프로미스는 단일 행동의 결과
2) 활동의 실패 또는 미수행에 대해 이를 알려주는데 사용됨
==> Ajax 사용시 뭔가 잘못되었음을 알려주는 중요한 기능
– 프로미스 체인: then( fn(result){ return result; })
– 프로미스 그룹핑: 프로미스 배열을 선언후 $q.all()로 실행
==> 모든 입력 프로미스가 리졸브되어야 리졸부 됨 (AND)
이에 대한 소스코드이다.
<!DOCTYPE html> <html ng-app="exampleApp"> <head> <title>DOM API Services - ProAngularJS</title> <link href="/node_modules/bootstrap/dist/css/bootstrap.css" rel="stylesheet" /> <link href="/node_modules/bootstrap/dist/css/bootstrap-theme.css" rel="stylesheet" /> /node_modules/angular/angular.js angular.module("exampleApp", []) .config( function( $httpProvider) { // $http의 모든 응답과 요청에 사용되는 기본 설정을 정의한다 $httpProvider.defaults.transformResponse.push( function( data, headers) { if( headers("content-type").split('/')[1] == "xml" && angular.isString(data)) { var products = []; var productElems = angular.element( data.trim()).find("product"); for( var i=0; i 일회성(프로미스는 단일 행동의 결과이다) // cf. 이에 반해 click event는 횟수 정보 없이 여러번 사용 가능 // 단 한번만 반드시 호출된다는 점에서 ajax 결과 알림에 매우 유용 if( buttonText == "Abort") { //deferred.reject("Aborted"); //console.log("deferred.reject('Aborted')"); deferred[buttonGroup].reject("Aborted"); } else { //deferred.resolve(buttonText); //console.log("deferred.resolve('"+buttonText+"')"); deferred[buttonGroup].resolve(buttonText); } }); }, controller: function( $scope, $element, $attrs) { // 디렉티브의 콘트롤러에 promise 객체를 저장 //this.promise = deferred.promise; // $q.all(): 모든 프로미스 이벤트가 만족되어야 실행된다 this.promise = $q.all( promises).then( function( results) { return results.join(); }); } }; }) .directive( "promiseObserver", function() { return { require: "^promiseWorker", link: function( scope, element, attrs, ctrl) { // then 프로미스는 success, error, notify를 인자로 갖는다 // 두번째 함수는 error시 호출됨 // promise-worker에서 저장된 promise 객체를 통해 span 텍스트로 출력 ctrl.promise.then( function( result) { return "2nd promise - Success ("+result+")"; }, function( reason) { element.text("1st promise - Fail ("+reason+")"); }) .then( function(result) { // promise 체인에 의한 두번째 promise 호출 element.text(result); }); } }; }) .controller("defaultCtrl", function( $scope, $http, $q, $rootScope) { $scope.loadJsonData = function() { $http.get("productData.json") .success( function( data) { $scope.products = data; }); }; /////////////////////// $scope.loadXmlData = function() { /* $http.get("productData.xml") .success( function( data) { $scope.products = []; var productElems = angular.element( data.trim()).find("product"); for( var i=0; i"); for( var i=0; i"); prodElem.attr("name", data[i].name); prodElem.attr("name", data[i].name); prodElem.attr("name", data[i].name); rootElem.append(prodElem) } rootElem.children().wrap(""); return rootElem.html(); } }; $http.post("ajax.html", $scope.products, config); }; function testDeferredAngularAsync() { var deferred = $q.defer(); deferred.promise.then(function(result) { console.log('promise success'); }, function(error) { console.log('promise error'); }); setTimeout(function() { console.log('resolving deferred'); deferred.resolve(); $rootScope.$apply(); }, 1500); }; // Works testDeferredAngularAsync(); }); </head> <body ng-controller="defaultCtrl"></div>
Name Category Price No Data {{ item.name }} {{ item.category }} {{ item.price | currency }} Load JSON Load XML
Send XML
Heads Tails AbortYes No AbortOutcome: <span promise-observer></span> </div> </body> </html>