AngularJS : 약속은 어디에 사용합니까?
FB Graph API에 액세스하기 위해 약속 을 사용하는 Facebook 로그인 서비스의 몇 가지 예를 보았습니다 .
예 # 1 :
this.api = function(item) {
var deferred = $q.defer();
if (item) {
facebook.FB.api('/' + item, function (result) {
$rootScope.$apply(function () {
if (angular.isUndefined(result.error)) {
deferred.resolve(result);
} else {
deferred.reject(result.error);
}
});
});
}
return deferred.promise;
}
"$scope.$digest() // Manual scope evaluation"
응답을 받았을 때 사용한 서비스
예 # 2 :
angular.module('HomePageModule', []).factory('facebookConnect', function() {
return new function() {
this.askFacebookForAuthentication = function(fail, success) {
FB.login(function(response) {
if (response.authResponse) {
FB.api('/me', success);
} else {
fail('User cancelled login or did not fully authorize.');
}
});
}
}
});
function ConnectCtrl(facebookConnect, $scope, $resource) {
$scope.user = {}
$scope.error = null;
$scope.registerWithFacebook = function() {
facebookConnect.askFacebookForAuthentication(
function(reason) { // fail
$scope.error = reason;
}, function(user) { // success
$scope.user = user
$scope.$digest() // Manual scope evaluation
});
}
}
질문은 :
- 위 예제 의 차이점 은 무엇입니까 ?
- 무엇입니까 이유 와 경우에 사용할 수있는 $ Q의 서비스는?
- 그리고 어떻게 작동 합니까?
이것은 귀하의 질문에 대한 완전한 대답은 아니지만 $q
서비스 에 대한 문서를 읽으려고 할 때 도움이 될 것 입니다. 그것을 이해하는 데 시간이 걸렸습니다.
잠시 AngularJS를 설정하고 Facebook API 호출을 고려해 봅시다. 두 API 호출 모두 콜백 메커니즘을 사용하여 Facebook의 응답이 사용 가능한 경우 호출자에게 알립니다.
facebook.FB.api('/' + item, function (result) {
if (result.error) {
// handle error
} else {
// handle success
}
});
// program continues while request is pending
...
이것은 JavaScript 및 기타 언어에서 비동기 작업을 처리하기위한 표준 패턴입니다.
이 패턴의 한 가지 큰 문제는 일련의 비동기 작업을 수행해야 할 때 발생하며, 각 연속 작업은 이전 작업의 결과에 따라 다릅니다. 이것이이 코드가하는 일입니다.
FB.login(function(response) {
if (response.authResponse) {
FB.api('/me', success);
} else {
fail('User cancelled login or did not fully authorize.');
}
});
먼저 로그인을 시도한 다음 로그인에 성공했는지 확인한 후에 만 그래프 API에 요청합니다.
이 경우에도 두 작업 만 연결하는 경우에도 문제가 발생하기 시작합니다. 이 메소드 askFacebookForAuthentication
는 실패와 성공에 대한 콜백을 수락하지만 FB.login
성공하지만 FB.api
실패 하면 어떻게됩니까 ? 이 메소드 success
는 FB.api
메소드 결과에 관계없이 항상 콜백을 호출합니다 .
이제 각 단계에서 오류를 올바르게 처리하고 몇 주 후에 다른 사람이나 사용자가 읽을 수있는 방식으로 강력한 3 개 이상의 비동기 작업 시퀀스를 코딩하려고한다고 상상해보십시오. 가능하지만 콜백을 중첩하고 길을 따라 오류를 추적하는 것은 매우 쉽습니다.
이제 잠시 동안 Facebook API를 제외하고 $q
서비스에서 구현 된대로 Angular Promises API를 고려해 봅시다 . 이 서비스에 의해 구현 된 패턴은 비동기 프로그래밍을 선형 일련의 간단한 명령문과 유사한 것으로 다시 변환하려는 시도로, 어떤 방식 으로든 오류를 '던지기'하고 결국에는이를 처리 할 수있는 능력을 갖습니다. 익숙한 try/catch
블록.
이 예를 생각해보십시오. 두 번째 함수가 있는데, 두 번째 함수는 첫 번째 함수의 결과를 사용합니다.
var firstFn = function(param) {
// do something with param
return 'firstResult';
};
var secondFn = function(param) {
// do something with param
return 'secondResult';
};
secondFn(firstFn());
firstFn과 secondFn을 모두 완료하는 데 시간이 오래 걸리므로이 시퀀스를 비동기 적으로 처리하려고합니다. 먼저 deferred
일련의 작업을 나타내는 새 객체를 만듭니다 .
var deferred = $q.defer();
var promise = deferred.promise;
이 promise
속성은 체인의 최종 결과를 나타냅니다. 약속을 만든 후 즉시 기록하면 약속이 빈 개체 ( {}
) 임을 알 수 있습니다 . 아직 볼 것이 없습니다.
지금까지 우리의 약속은 체인의 출발점만을 나타냅니다. 이제 두 가지 작업을 추가하겠습니다 :
promise = promise.then(firstFn).then(secondFn);
이 then
방법은 체인에 단계를 추가 한 다음 확장 된 체인의 최종 결과를 나타내는 새로운 약속을 반환합니다. 원하는만큼 단계를 추가 할 수 있습니다.
지금까지 함수 체인을 설정했지만 실제로는 아무 일도 일어나지 않았습니다. deferred.resolve
체인의 첫 번째 실제 단계에 전달하려는 초기 값을 지정하여을 호출 하여 작업을 시작합니다 .
deferred.resolve('initial value');
And then...still nothing happens. To ensure that model changes are properly observed, Angular doesn't actually call the first step in the chain until the next time $apply
is called:
deferred.resolve('initial value');
$rootScope.$apply();
// or
$rootScope.$apply(function() {
deferred.resolve('initial value');
});
So what about error handling? So far we have only specified a success handler at each step in the chain. then
also accepts an error handler as an optional second argument. Here's another, longer example of a promise chain, this time with error handling:
var firstFn = function(param) {
// do something with param
if (param == 'bad value') {
return $q.reject('invalid value');
} else {
return 'firstResult';
}
};
var secondFn = function(param) {
// do something with param
if (param == 'bad value') {
return $q.reject('invalid value');
} else {
return 'secondResult';
}
};
var thirdFn = function(param) {
// do something with param
return 'thirdResult';
};
var errorFn = function(message) {
// handle error
};
var deferred = $q.defer();
var promise = deferred.promise.then(firstFn).then(secondFn).then(thirdFn, errorFn);
As you can see in this example, each handler in the chain has the opportunity to divert traffic to the next error handler instead of the next success handler. In most cases you can have a single error handler at the end of the chain, but you can also have intermediate error handlers that attempt recovery.
To quickly return to your examples (and your questions), I'll just say that they represent two different ways to adapt Facebook's callback-oriented API to Angular's way of observing model changes. The first example wraps the API call in a promise, which can be added to a scope and is understood by Angular's templating system. The second takes the more brute-force approach of setting the callback result directly on the scope, and then calling $scope.$digest()
to make Angular aware of the change from an external source.
The two examples are not directly comparable, because the first is missing the login step. However, it's generally desirable to encapsulate interactions with external APIs like this in separate services, and deliver the results to controllers as promises. That way you can keep your controllers separate from external concerns, and test them more easily with mock services.
I expected a complex answer that will cover both: why they are used in general and how to use it in Angular
This is the plunk for angular promises MVP (minimum viable promise): http://plnkr.co/edit/QBAB0usWXc96TnxqKhuA?p=preview
Source:
(for those too lazy to click on the links)
index.html
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.1.5/angular.js"></script>
<script src="app.js"></script>
</head>
<body ng-app="myModule" ng-controller="HelloCtrl">
<h1>Messages</h1>
<ul>
<li ng-repeat="message in messages">{{ message }}</li>
</ul>
</body>
</html>
app.js
angular.module('myModule', [])
.factory('HelloWorld', function($q, $timeout) {
var getMessages = function() {
var deferred = $q.defer();
$timeout(function() {
deferred.resolve(['Hello', 'world']);
}, 2000);
return deferred.promise;
};
return {
getMessages: getMessages
};
})
.controller('HelloCtrl', function($scope, HelloWorld) {
$scope.messages = HelloWorld.getMessages();
});
(I know it doesn't solve your specific Facebook example but I find following snippets useful)
Via: http://markdalgleish.com/2013/06/using-promises-in-angularjs-views/
Update 28th Feb 2014: As of 1.2.0, promises are no longer resolved by templates. http://www.benlesh.com/2013/02/angularjs-creating-service-with-http.html
(plunker example uses 1.1.5.)
A deferred represents the result of an asynchronic operation. It exposes an interface that can be used for signaling the state and the result of the operation it represents. It also provides a way to get the associated promise instance.
A promise provides an interface for interacting with it’s related deferred, and so, allows for interested parties to get access to the state and the result of the deferred operation.
When creating a deferred, it’s state is pending and it doesn’t have any result. When we resolve() or reject() the deferred, it changes it’s state to resolved or rejected. Still, we can get the associated promise immediately after creating a deferred and even assign interactions with it’s future result. Those interactions will occur only after the deferred rejected or resolved.
use promise within a controller and make sure the data is available or not
var app = angular.module("app",[]);
app.controller("test",function($scope,$q){
var deferred = $q.defer();
deferred.resolve("Hi");
deferred.promise.then(function(data){
console.log(data);
})
});
angular.bootstrap(document,["app"]);
<!DOCTYPE html>
<html>
<head>
<script data-require="angular.js@*" data-semver="1.3.0-beta.5" src="https://code.angularjs.org/1.3.0-beta.5/angular.js"></script>
</head>
<body>
<h1>Hello Angular</h1>
<div ng-controller="test">
</div>
</body>
</html>
참고URL : https://stackoverflow.com/questions/15604196/angularjs-where-to-use-promises
'IT story' 카테고리의 다른 글
JavaScript에서 매개 변수없이 URL을 얻는 방법은 무엇입니까? (0) | 2020.06.19 |
---|---|
.gitconfig를 사용하여 diff 도구 구성 (0) | 2020.06.19 |
Xcode는 각 키 입력 후 스토리 보드를 계속 작성합니다. (0) | 2020.06.19 |
인스턴스의 클래스가 인터페이스를 구현하는지 확인하고 있습니까? (0) | 2020.06.19 |
CSS가 요소의 각 단어 다음에 줄 바꿈을 강제 할 수 있습니까? (0) | 2020.06.19 |