13

I'm having a lot of trouble with this and I can't seem to find anything here on SO or Google that helps me spot what I'm doing wrong

<!DOCTYPE html>
<html data-ng-app="testApp">
   <head>
      <title></title>
   </head>
   <body>
      <div data-ng-controller="myController">
         {{test}}<br/>
         {{test2}}<br/>
         {{test3}}
         <ul>
            <li data-ng-repeat="member in members">{{ member.firstname}}</li>
         </ul>
      </div>
      <script type="text/javascript" src="angular.min.js"></script>
      <script type="text/javascript">
         angular.module('testApp', ['memberFactory']);

         angular.module('testApp',[])
         .factory('memberFactory', function($http){

            var obj = {};
            obj.data = "abcd";
            obj.getResponse = function(){
                var temp = {};
                $http.get('hello.php').success(function(data){
                        alert(data);
                        temp =data;

                });

                return "some return value";
            }

            return obj
         });

         function myController($scope, memberFactory){ 
            $scope.test= "testString";
            $scope.test2= memberFactory.data;
            $scope.test3= memberFactory.getResponse();

         }
      </script>
   </body>
</html>

the return "some return value"; works but when I try to return temp, its null. I have tried various ways to get this to work but I just can't seem to set the temp value inside the $http.get() function

It is probably something simple (or a silly mistake/misguided approach on my part). Any advice would be greatly appreciated

jonnie
  • 12,260
  • 16
  • 54
  • 91

3 Answers3

24

Use defer:

obj.getResponse = function(){                 
    var temp = {};
    var defer = $q.defer();
    $http.get('hello.php').success(function(data){
            alert(data);
            temp =data;
            defer.resolve(data);

    });
    return defer.promise;
}
AlwaysALearner
  • 43,759
  • 9
  • 96
  • 78
  • 2
    What is $q? I'm getting not defined. is this another library? – jonnie Aug 07 '13 at 11:19
  • 2
    It has to be injected in the same manner as `$http`. It's the AngularJS implementation of the promise/defer pattern. – Steve Klösters Aug 07 '13 at 11:19
  • @CodeZilla ok, but now it returns `{"promise":{}}` instead of nothing so I still cannot access my data, any Ideas? – jonnie Aug 07 '13 at 11:25
  • Try using "then" instead of "success". What does the alert show? I dont think using "success" is a problem. – AlwaysALearner Aug 07 '13 at 11:32
  • @Codezilla I tried `then` and still same issue, the alert inside the `get` displays `[{"ID":"1","firstname":"John","surname":"Smith"},{"ID":"2","firstname":"Jack","surname":"Jones"}]` – jonnie Aug 07 '13 at 11:56
  • 1
    Yep. Try returning the promise as suggested by @Matt Cooper. – AlwaysALearner Aug 07 '13 at 11:58
  • @Codezilla I was just missing `defer.$apply()` Thanks for your help, if you want to add the $apply to your answer I will accept your answer – jonnie Aug 07 '13 at 12:03
  • Not sure why it didn't, but now it suddenly is... which is odd – jonnie Aug 07 '13 at 12:11
  • 1
    redundant use of $q. $http returns a promise object obj.getResponse = function(){ var temp = {}; return $http.get('hello.php').success(function(data){ alert(data); temp =data; }); } – Brian Vanderbusch Mar 03 '14 at 09:06
  • @BrianVanderbusch how do you resolve the defered $http returns? – Marcelo Mason Jul 31 '15 at 21:10
14

What's happening here is a result of the asynchronous nature of $http.get, When you run $http.get it doesn't run in order. That is, it 'branches off' and runs along side the rest of the code. This is done to accommodate for the server latency.

Here's a bad visualisation.

.getResponse Called                Return Temp.
|-------------------|--------------|
                    |---------------------------------|
                    $http.get ~Waiting for Server~    Temp assigned to data.

Can you see how Temp is returned before it's been given a value?

Thankfully, you can use what Angular calls a promise, This is a variable which you can return from a function, that gets 'resolved' later. You instantiate a promise like this.

var myPromise = $q.defer();

You assign values to it by using

myPromise.resolve(data);

You can then return this promise later in the function, in the normal way. ie.

return myPromise.promise

Of course, for all of this you need the $q library, which you include in the function parameters.

Matt Cooper
  • 1,004
  • 7
  • 12
  • Whoops, didn't see Codezilla's answer before I posted, they have the right idea. I'll leave this up as an explanation though. – Matt Cooper Aug 07 '13 at 11:24
  • Thanks for the Explanation, unfortunately I now just get `{"promise":{}} ` – jonnie Aug 07 '13 at 11:30
  • Terribly sorry! just noticed a bug in my code. You need to return myPromise.promise (as in, the actual promise object!) Should work then. Sorry for leading you astray! – Matt Cooper Aug 07 '13 at 11:52
  • What I meant was that I still get null, What I get is `{ "promise": {}}` what I think I should be getting it `{"promise": [{"ID":"1","firstname":"John","surname":"Smith"},{"ID":"2","firstname":"Jack","surname":"Jones"}]}` – jonnie Aug 07 '13 at 11:59
  • I managed to get it, I just needed to call `mypromise.$apply()` Thanks – jonnie Aug 07 '13 at 12:02
  • Excellent, I wouldn't have expected you to have to $apply() though, I managed to get it working on this plunk (http://plnkr.co/edit/gUqz1Q0jUfXhkAJThTaK) for what it's worth. Good luck! – Matt Cooper Aug 07 '13 at 12:04
  • @MattCooper Thank you for the return myPromise.promise part. Dint knew that. Voted up! :) – AlwaysALearner Aug 07 '13 at 12:17
  • Sorry. Where and how you used $apply? Trying to understand this promises thing, but ... – Федор Усаков Oct 28 '15 at 17:46
0
//in  $httpProvider.interceptors    
if (typeof response.data === 'string') {
   return response;
}
else {
  return response.data;
}
ivan Ying
  • 11
  • 3
  • Can you please explain what are you exactly doing in answer. It will be help to understand. Simply writing code not gonaa give clearity. – UDID Mar 30 '17 at 06:24