angularjs에서 $ http 요청에서 응답이 올 때까지 기다리는 방법은 무엇입니까?


93

여러 페이지에서 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에서 그렇게합니까?

답변:


150

언제 완료 될지 모르는 비동기 작업에는 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 () 호출이 트리거됩니다. 따라서 코드의 흐름을 좀 더 복잡하게 만들더라도이 방법은 훨씬 더 합리적입니다 (복잡성은 일반적으로 비동기 / 병렬 프로그래밍의 일반적인 문제입니다!).


2
이것은 내 문제를 해결했습니다! 다른 사람에게는 ajax 호출의 데이터가 필요한 드롭 다운이 있었기 때문에 범위가 생성되었을 때 데이터를 사용할 수 없었습니다. 이 지연을 통해 범위는 ajax 호출에서 오는 데이터를 갖도록 할당 될 수 있습니다.
Kat Lim Ruiz

8
@mikel : 여기에 또 다른 질문이 있습니다. myFuction () 호출은 즉시 반환되지만 약속 .then ()은 나중에 호출됩니다. .then () 함수가 실행을 마칠 때까지 myFuction () 호출이 반환되지 않도록하려면 어떻게해야합니까? 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."); }
Sujoy

13

이것에 익숙하지 않은 사람들을 위해 다음과 같이 콜백을 사용할 수도 있습니다.

귀하의 서비스에서 :

.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;
   });

훌륭한 솔루션입니다. 내가 그것을 들여다 볼 때이 같은 선을 따라 생각하고 있었다. 누군가 이걸 내놓아 기뻐요.
Nate

0

참고로, 이것은 Angularfire를 사용하고 있으므로 다른 서비스 또는 기타 용도에 따라 약간 다를 수 있지만 $ http가 가진 동일한 문제를 해결해야합니다. 나에게 가장 적합한 유일한 해결책은 모든 서비스 / 공장을 범위에 대한 단일 약속으로 결합하는 것이 었습니다. 이러한 서비스 / 등을로드해야하는 각 경로 /보기에서로드 된 데이터를 필요로하는 함수를 컨트롤러 함수, 즉 myfunct () 및 기본 app.js 내부에 넣습니다.

myservice.$loaded().then(function() {$rootScope.myservice = myservice;});

보기에서 방금

ng-if="myservice" ng-init="somevar=myfunct()"

컨트롤러가 내부에서 모든 것을 실행할 수 있도록 첫 번째 / 부모보기 요소 / 래퍼에서

myfunct()

비동기 약속 / 주문 / 대기열 문제에 대해 걱정하지 않아도됩니다. 나는 그것이 내가 가진 것과 같은 문제를 가진 사람에게 도움이되기를 바랍니다.


0

나는 똑같은 문제를 겪고 있었고 이것이 나를 위해 일한다면 아무것도 없었습니다. 그래도 작동 한 것은 다음과 같습니다 ...

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를 사용할 때 다른 것입니다. 어쨌든 도움이 되었기를 바랍니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.