약속을 돌려주는 각진 공장
앱이 시작되면 서버에서 설정을 로드합니다.대부분의 컨트롤러는 유용한 작업을 수행하기 전에 이 기능을 필요로 합니다.컨트롤러의 코드를 가능한 한 간단하게 하고 싶습니다.내 시도는 실패했지만, 다음과 같다.
app.factory('settings', ['$rootScope', '$http', '$q', function($rootScope, $http, $q) {
var deferred = $q.defer();
$http.get('/api/public/settings/get').success(function(data) {
$rootScope.settings = data;
deferred.resolve();
});
return deferred.promise;
}]);
app.controller('SomeCtrl', ['$rootScope', 'settings', function($rootScope, settings) {
// Here I want settings to be available
}]);
설정이 많은 것은 피하고 싶다.그러면 (function()...
어떻게 하면 이 문제를 잘 해결할 수 있을까?
$http 자체는 $q 안에 바인드할 필요가 없다는 약속을 반환합니다.이것은 좋은 프랙티스가 아니고, Anti Pattern으로 간주됩니다.
용도:-
app.factory('settings', ['$rootScope', '$http', '$q', function($rootScope, $http) {
return $http.get('/api/public/settings/get')
}]);
app.controller('SomeCtrl', ['settings',$scope, function(settings,$scope) {
settings.then(function(result){
$scope.settings=result.data;
});
}]);
방법은 다음과 같습니다.
app.factory('settings', ['$rootScope', '$http', '$q', function($rootScope, $http, $q) {
var deferred = $q.defer();
$http.get('/api/public/settings/get').success(function(data) {
deferred.resolve(data);
});
return deferred.promise;
}]);
app.controller('SomeCtrl', ['$scope', 'settings', function($scope, settings) {
settings.then(function(data){
$scope.settings=data;
})
}]);
$rootScope의 변경에 $watch를 사용해야 하는 경우 $rootScope를 오버로드하지 마십시오(권장되지 않음).
"기다려야 할 곳"입니다.
Angular에 내장되어 있는 유일한 방법은 컨트롤러가 비동기 데이터를 로드하기 위해 스스로 대기하는 것을 완전히 배제하는 것입니다.$routeProvider
의 루트resolve
재산(또는 대체품)$stateProvider
의ui.router
모든 약속이 해결되고 해결된 데이터가 삽입될 때만 컨트롤러가 실행됩니다.
그래서, ng-route 대안 - plunker:
$routeProvider.when("/", {
controller: "SomeCtrl",
templateUrl: "someTemplate.html",
resolve: {
settings: function(settingsSvc){
return settingsSvc.load(); // I renamed the loading function for clarity
}
});
그럼, 인SomeCtrl
추가할 수 있습니다.settings
주입 가능한 의존관계로서:
.controller("SomeCtrl", function($scope, settings){
if (settings.foo) $scope.bar = "foo is on";
})
로딩할 때까지 "대기"someTemplate
에<div ng-view></div>
설정이 해결될 때까지.
그settingsSvc
는 HTTP 요청을 다시 실행할 필요가 없도록 약속을 캐시해야 합니다.주의: 다른 답변에서 언급한 바와 같이,$q.defer
사용하고 있는 API가$http
)는 이미 약속을 반환합니다.
.factory("settingsSvc", function($http){
var svc = {settings: {}};
var promise = $http.get('/api/public/settings/get').success(function(data){
svc.settings = data; // optionally set the settings data here
});
svc.load = function(){
return promise;
}
return svc;
});
또 다른 접근법이 마음에 들지 않으면ngRoute
그 방법, 예를 들어,settings
서비스 브로드캐스트$rootScope
설정이 로드되고 컨트롤러가 이에 반응하여 모든 작업을 수행할 수 있는 이벤트입니다.하지만 그게 더 '무거운' 것 같아.then
.
세 번째 방법인 plunker는 모든 종속성이 미리 로드되어 있을 때만 앱 수준의 컨트롤러를 "활성화"하는 것이라고 생각합니다.
.controller("AppCtrl", function($q, settingsSvc, someOtherService){
$scope.loaded = false;
$q.all([settingsSvc.load, someOtherService.prefetch]).then(function(){
$scope.loaded = true;
});
});
[보기(View)]그래서,ng-if
와 함께loaded
:
<body ng-controller="AppCtrl">
<div ng-if="!loaded">loading app...</div>
<div ng-if="loaded">
<div ng-controller="MainCtrl"></div>
<div ng-controller="MenuCtrl"></div>
</div>
</body>
최소 이 정의의 애플리케이션 루트 상태를 가지면 이 작업을 쉽게 수행할 수 있습니다.
$stateProvider
.state('app', {
abstract: true,
template: '<div ui-view></div>'
resolve: {
settings: function($http){
return $http.get('/api/public/settings/get')
.then(function(response) {return response.data});
}
}
})
그 후 모든 응용 프로그램 상태를 이 루트 상태에서 상속할 수 있습니다.
- 모든 컨트롤러는 설정이 로드된 후에만 실행됩니다.
- 모든 컨트롤러는 가능한 한 주입 가능한 설정으로 해결된 값에 액세스할 수 있습니다.
전술한 바와 같이 해결은 원래 ng-route에서도 기능하지만 네스트를 지원하지 않기 때문에 이 접근법은 ui-router만큼 유용하지 않습니다.
설정이 로드된 후 애플리케이션을 수동으로 부트스트랩할 수 있습니다.
var initInjector = angular.injector(["ng"]);
var $http = initInjector.get("$http");
var $rootScope = initInjector.get("$rootScope");
$http.get('/api/public/settings/get').success(function(data) {
$rootScope.settings = data;
angular.element(document).ready(function () {
angular.bootstrap(document, ["app"]);
});
});
이 경우 설정이 로드된 후에만 전체 응용 프로그램이 실행됩니다.
자세한 내용은 각도 부트스트랩 설명서를 참조하십시오.
언급URL : https://stackoverflow.com/questions/28830003/angular-factory-returning-a-promise
'programing' 카테고리의 다른 글
Azure 웹 사이트 구독 변경 (0) | 2023.05.18 |
---|---|
grep, awk, sed의 차이점은 무엇입니까? (0) | 2023.05.18 |
json_encode()가 잘못된 문자를 가진 문자열을 삭제하지 않도록 하는 방법 (0) | 2023.03.19 |
PHP fopen() 오류: 스트림을 열지 못했습니다.권한 거부 (0) | 2023.03.19 |
ESLint broken: 제안이 있는 규칙은 "meta.has Suggestions" 속성을 "true"로 설정해야 합니다. (0) | 2023.03.19 |