여러 페이지에서 RESTful 서비스의 일부 데이터를 사용하고 있습니다. 그래서 저는 그것을 위해 앵귤러 팩토리를 사용하고 있습니다. 따라서 서버에서 데이터를 한 번 가져와야했고, 정의 된 서비스로 데이터를 가져올 때마다 필요했습니다. 전역 변수와 같습니다. 다음은 샘플입니다.
var myApp = angular.module('myservices', []);
myApp.factory('myService', function($http) {
$http({method:"GET", url:"/my/url"}).success(function(result){
return result;
});
});
내 컨트롤러에서이 서비스를 다음과 같이 사용하고 있습니다.
function myFunction($scope, myService) {
$scope.data = myService;
console.log("data.name"+$scope.data.name);
}
내 요구 사항에 따라 잘 작동합니다. 그러나 여기서 문제는 웹 페이지에서 다시로드 할 때 서비스가 다시 호출되고 서버에 대한 요청이 있다는 것입니다. “정의 된 서비스”에 종속 된 다른 함수가 실행되는 사이에 “무언가”가 정의되지 않은 것과 같은 오류가 발생합니다. 그래서 서비스가로드 될 때까지 스크립트에서 기다리고 싶습니다. 어떻게 할 수 있습니까? 어쨌든 angularjs에서 그렇게합니까?
답변
언제 완료 될지 모르는 비동기 작업에는 promise를 사용해야합니다. 약속은 “아직 완료되지 않았지만 미래에 예상되는 작업을 나타냅니다.” ( https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Promise )
구현 예는 다음과 같습니다.
myApp.factory('myService', function($http) {
var getData = function() {
// Angular $http() and then() both return promises themselves
return $http({method:"GET", url:"/my/url"}).then(function(result){
// What we return here is the data that will be accessible
// to us after the promise resolves
return result.data;
});
};
return { getData: getData };
});
function myFunction($scope, myService) {
var myDataPromise = myService.getData();
myDataPromise.then(function(result) {
// this is only run after getData() resolves
$scope.data = result;
console.log("data.name"+$scope.data.name);
});
}
편집 : Sujoys와 관련하여 myFuction
() 호출이 .then () 함수가 실행을 완료 할 때까지 반환되지 않도록해야 할 일은 무엇입니까?
function myFunction($scope, myService) {
var myDataPromise = myService.getData();
myDataPromise.then(function(result) {
$scope.data = result;
console.log("data.name"+$scope.data.name);
});
console.log("This will get printed before data.name inside then. And I don't want that.");
}
자, getData () 호출이 완료되는 데 10 초가 걸린다고 가정 해 보겠습니다. 그 시간에 함수가 아무 것도 반환하지 않으면 사실상 정상적인 동기 코드가되어 완료 될 때까지 브라우저를 멈 춥니 다.
약속이 즉시 반환되면 브라우저는 그 동안 다른 코드를 계속 사용할 수 있습니다. 약속이 해결 / 실패하면 then () 호출이 트리거됩니다. 따라서 코드의 흐름을 좀 더 복잡하게 만들더라도이 방법은 훨씬 더 합리적입니다 (복잡성은 일반적으로 비동기 / 병렬 프로그래밍의 일반적인 문제입니다!).
답변
이것에 익숙하지 않은 사람들을 위해 다음과 같이 콜백을 사용할 수도 있습니다.
귀하의 서비스에서 :
.factory('DataHandler',function ($http){
var GetRandomArtists = function(data, callback){
$http.post(URL, data).success(function (response) {
callback(response);
});
}
})
컨트롤러에서 :
DataHandler.GetRandomArtists(3, function(response){
$scope.data.random_artists = response;
});
답변
참고로, 이것은 Angularfire를 사용하고 있으므로 다른 서비스 또는 기타 용도에 따라 약간 다를 수 있지만 $ http가 가진 동일한 문제를 해결해야합니다. 나에게 가장 적합한 유일한 해결책은 모든 서비스 / 공장을 범위에 대한 단일 약속으로 결합하는 것이 었습니다. 이러한 서비스 / 등을로드해야하는 각 경로 /보기에서로드 된 데이터를 필요로하는 함수를 컨트롤러 함수, 즉 myfunct () 및 기본 app.js 내부에 넣습니다.
myservice.$loaded().then(function() {$rootScope.myservice = myservice;});
보기에서 방금
ng-if="myservice" ng-init="somevar=myfunct()"
컨트롤러가 내부에서 모든 것을 실행할 수 있도록 첫 번째 / 부모보기 요소 / 래퍼에서
myfunct()
비동기 약속 / 주문 / 대기열 문제에 대해 걱정하지 않아도됩니다. 나는 그것이 내가 가진 것과 같은 문제를 가진 사람에게 도움이되기를 바랍니다.
답변
나는 똑같은 문제를 겪고 있었고 이것이 나를 위해 일한다면 아무것도 없었습니다. 그래도 작동 한 것은 다음과 같습니다 …
app.factory('myService', function($http) {
var data = function (value) {
return $http.get(value);
}
return { data: data }
});
그리고 그것을 사용하는 기능은 …
vm.search = function(value) {
var recieved_data = myService.data(value);
recieved_data.then(
function(fulfillment){
vm.tags = fulfillment.data;
}, function(){
console.log("Server did not send tag data.");
});
};
서비스가 그다지 필요하지는 않지만 확장 성을위한 좋은 방법이라고 생각합니다. 하나에 필요한 대부분은 특히 API를 사용할 때 다른 것입니다. 어쨌든 도움이 되었기를 바랍니다.