들어가며
$timeout 서비스는window.setTimeout 을 사용하기 위한 Angular의 래퍼로, 대상이되는 함수(fn)는 자동적으로 try / catch 블록으로 처리되어 $exceptionHandler 서비스에서 에러를 컨트럴할 수 있게 된다.
timeout 함수를 등록했을 때의 promise 객체를 리턴하게 되는데, 이 promise는 timeout이 지정 시간에 도달하고 그 timeout 함수가 실행 될 때 resolve 된다.
window.setTimeout과는 달리 $timeout은 Promise 를 리턴하기 때문에 이전에 콜백으로 접근하는 방식의 코드가 아닌 promise 기반의 더 나은 코딩을 할 수 있는 장점이 있다. $timeout 의 첫번째 파라메터인 콜백 함수에서 값을 리턴하게 되면 이 값은 promise가 resolve 되었을 때 전달된다.
$timeout 서비스 사용방법
$timeout(fn [, delay ] [, invokeApply ]);
fn
지연 실행되어야 함수를 지정한다.
delay (optional)
지연시키는 시간을 밀리 초 단위로 지정하며 초기 값은 0이다.
invokeApply (optional)
만약 false로 설정하면 model dirty check를 생략하고, 그렇지 않으면 $apply 블록에서 fn을 실행한다.
리턴값
$timeout(fn [, delay ] [, invokeApply ]) 를 실행하면, Promise 객체를 리턴받게 된다. timeout이 지정 시간에 도달했을 때 resolve되는 Promise 로써, 이 promise가 resolve 될 경우, fn 함수의 반환 값을 반환한다.
$timeout.cancel(promise)
promise 관련 작업을 취소하는 메서드로, 이 메서드를 실행하면, promise는 reject 된다.
이 메서드 시행 시 $timeout 에 지정한 fn의 작업이 아직 실행되지 않고 취소에 성공했을 경우는 true를 돌려준다.
$timeout.flush()
테스트에서는 deferred 함수의 큐를 동시에 수행하기 위해 $ timeout.flush() 를 사용할 수 있다.
$timeout(function () {
//지연된 작업이 여기에 위치한다.
return 123; //리턴값 123은 promise의 resolve 콜백에 파라메터로 전달된다.
}, 1000 /* 1000ms 뒤에 지연된 작업이 수행된다. */, true );
$timeout의 invokeApply 파라메터
$timeout 서비스의 세번째 파라메터인 invokeApply 에 대해서 더 깊이 파고들어 보자.
이 파라메터는 생략할 경우 기본값은 true로, false일 경우 AngularJS의 digest loops에서 model dirty check를 하지 않게 된다.
$timeout 서비스를 통해 수행하는 지연작업이 별도로 scope 내의 변수를 수정하지 않는 작업이라면, 굳이 model dirty check를 해서 부하를 증가시킬 필요는 없기 때문에 이 세번째 파라메터를 false 로 주면 성능 향상에 미미하게나마 도움이 될 것이다.
하지만 invokeApply 파라메터를 false로 줄 경우, AngularJS 1.0.x 버전의 경우 $timeout 의 Promise가 resolve 되지 않는 문제가 있다. 현재 최신 버전인 1.3.8 에서는 정상적으로 동작하지만, 이런 문제로 인해 invokeApply 파라메터를 사용할 때는 주의할 필요가 있다.
invokeApply를 true로 줄 경우 $rootScope에서 $apply() 를 해주기 때문에 이하 모든 child 스코프에도 모두 적용되게 된다.
AngularJS 표현식에서의 Promise
AngularJS의 표현식에서 Promise는 resolve 여부에 따라 아래와 같이 활용할 수 있다.
function promiseCtrl($scope, $timeout) {
$scope.result = $timeout(function({
return "Ready!";
}, 1000);
}
<div ng-controller="promiseCtrl">
{{result || "Preparing…"}}
</div>
마치며
지금까지 AngularJS의 $timeout 서비스에 대해서 살펴보았다. window.setTimeout 의 래퍼 서비스에 가깝지만, 미묘한 차이점에 대해서 명확히 이해하지 못하면 실제 어플리케이션에서 예상하지 못한 결과를 만나기 쉽다. 실제로 invokeApply 파라메터를 수정하면서 예상과 다른 결과가 나와 이를 수정하기 위해 많은 고생을 하기도 했다.
$timeout은 setTimeout과 달리 Promise를 리턴한다는 것과, invokeApply 파라메터로 model dirty check 여부를 결정할 수 있다는 사실에 대해서 기억하고 AngularJS 어플리케이션을 개발할 수 있기를 기대한다.