Re: [angular.js] Re: synchronous $http

17,814 views
Skip to first unread message

Peter Bacon Darwin

unread,
Jul 18, 2012, 10:38:47 AM7/18/12
to ang...@googlegroups.com

Or you could use the promise from $http

Pete
...from my mobile.

On Jul 18, 2012 3:34 PM, "Freewind" <nowi...@gmail.com> wrote:
That's working, thanks!

And the "$scope.watch("vio", function() {}" can do the same,right?

I still hope to find a way not have to use a callback, just do:

    doSimethingWith($scope.vio)

But I think it may be impossible.


On Wednesday, July 18, 2012 10:10:41 PM UTC+8, Ricardo Bin wrote:
You can do this using events.

When the ajax request is done, send a $broadcast to InnerCtrl with data value. The InnerCtrl need have an observer  $on too.

I simulate your async request on a button click in this fiddle: http://jsfiddle.net/ricardohbin/xxXMu/


Em quarta-feira, 18 de julho de 2012 10h38min56s UTC-3, Freewind escreveu:
When a page is loaded, there is a very important object should be retrieved from $http, and all other logic are based on it. So my code is:

    $http(..., function(data) {
         $scope.vio = data;
         // other logic are all based on the "vio"
    });

Now I split the code into several controllers, a root one, and some inner ones. To simplify the code, I want to get the "vio" in root controller, and other controllers are just use it. The code will be:

    function RootCtrl($scope, $http) {
         $http(..., function(data) {
             $scope.vio = data;
             // other logic are all based on the "vio"
        });
    }

    function InnerCtrl($scope, $http) {
         // do something with $scope.vio
         // e.g console.log($scope.vio);
    }

But since $http is asynchronous, I can't just use `$scope.vio` which may be 'undefined'.

How to solve this problem? How to make the $http call synchronous, or wait "vio" non-undefined in InnerCtrl?

--
You received this message because you are subscribed to the Google Groups "AngularJS" group.
To view this discussion on the web visit https://groups.google.com/d/msg/angular/-/I-wKgzeSQDUJ.
To post to this group, send email to ang...@googlegroups.com.
To unsubscribe from this group, send email to angular+u...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/angular?hl=en.

chris...@gmail.com

unread,
Jul 18, 2012, 10:22:51 PM7/18/12
to ang...@googlegroups.com
You could $watch on the vio in your InnerCtrl .

Chris.

Aki

unread,
Nov 19, 2012, 7:18:49 AM11/19/12
to ang...@googlegroups.com
Hi Pete,

Can u share lil more info on how to use Promise for doing a sync $http calls? any pointers would be really helpful. 

Peter Bacon Darwin

unread,
Nov 19, 2012, 7:29:57 AM11/19/12
to ang...@googlegroups.com
You can't do synchronous $http calls.  You can use Promises to make your code more readable and maintainable.  The basic idea is that $http methods do not return the data from the request, they return a "promise" that will allow you to get the data:

var promise = $http.get(...);
...
promise.then(function(data) {
  ... do stuff with data here ...
});

The nice thing about this is that you can pass these promises around to whoever might need them and they don't need to know anything about $http and you don't have to inject callbacks all the way back to the $http service. For example:

var getUser = function() {
  return $http.get(...);
};

...

getUser().then(function(data) {
  ...  do stuff with data here
});

You can chain promises together to filter or modify what will be passed to the then function further down the line.  Imagine your http.get returned this as its data: { user: { userName: 'pete', password: 'SECRET!' } }.  You can write functions like this:

var getUser = function() {
   return $http.get(...).then(function(data) {
     return data.user;   // Here we are extracting the user object from the data object
   });
}
var getUserName = function() {
  return getUser().then(function(user) {
    return user.userName;  // Here we extract the userName from the user object
  });
}

Now you have two options for getting this onto the scope.  The conventional (method of least surprise) is to use another then call:

getUserName().then(function(userName) {
  $scope.userName = userName;
});

When the http request returns you will get userName on the scope.

The AngularJS engine knows about promises so you can also save a bit of typing by doing this sneaky thing:

$scope.userName = getUserName();

This actually puts the promise onto the scope but AngularJS will realise this and unwrap the value when the promise is resolved.

Hope that helps...

Pete

Aki

unread,
Nov 20, 2012, 6:39:47 AM11/20/12
to ang...@googlegroups.com
Hi Pete,

Thanks for the details, that was really helpful :)

The issue tat am facing is similar to the original question of this thread. 

I have created a common service for doing all the $http calls. This service will be injected into the required controllers.

Also, i have created a interceptor to handle 403 responses. 

Issue is, in my controller i need to call the server via this $http service , get the response and based on the response do some manipulation.

Now since $http being async always, it doesnt wait for the response and directly runs the next line of code in the controller which leads to 'undefined' error.

previously, In xhr i have used callBack functions and al, but not sure how to handle this using $http. i.e without the $broadcast/$on is there any other method?

Peter Bacon Darwin

unread,
Nov 20, 2012, 6:45:21 AM11/20/12
to ang...@googlegroups.com
You simply chain a then(callback) on the end of your call to your service:

function myController($scope, myHttpService) {
  myHttpService.get().then(function(data) {
    // do what you need with the data
  });

Edward

unread,
Jan 15, 2013, 1:44:56 AM1/15/13
to ang...@googlegroups.com
Hi Peter,

I want to provide a service which stores some basic data retrieved from the backend via $http, then I need only fetch those data once. like,

    module.factory("basicDataProvider", function() { 
        var basicData;
        var getBasicData = function() {
            if(!basicData) {
                  httpService.get().then(function(data) {
                       basicData = data;
                  });
            }
            return basicData;
        };
        return {
               getBasicData : geBasiceData
        }
    });  

I may call this method like  
    function myController($scope, basicDataProvider) {
         var basicData = basicDataProvider.getBasicData(); 
   });
 

Then, the problem is the promise chain ends in basicDataProvider but not in controller, so the basicData is undefined the first time I use this controller  
since the data has not been returned.

Do you have any suggestions on this? Thanks a lot.


在 2012年11月20日星期二UTC+8下午7时45分45秒,Peter Bacon Darwin写道:

Peter Bacon Darwin

unread,
Jan 15, 2013, 8:44:47 AM1/15/13
to ang...@googlegroups.com
Return the promise to the controller instead of the data.


Edward

unread,
Jan 16, 2013, 12:59:21 AM1/16/13
to ang...@googlegroups.com
Thanks Peter, I have resolved the problem

在 2013年1月15日星期二UTC+8下午9时44分47秒,Peter Bacon Darwin写道:

JC

unread,
Oct 28, 2016, 3:08:12 AM10/28/16
to Angular
hello Peter,

I have been doing what you have suggested. 

The problem is that I need to issue a $http call to retrieve some information. Then, after this, and having a successful response, I need to call a 2nd $http that uses as input parameters some data retrieved from the 1st one and so on. I mean, I have a series of $http that are dependant on each other. 

My concern is about code cohesion. Because I can only call the next given $http from within the "then(callback)" of the previous one, I end up having a function that actually have many purposes. For example:

some code here...
retrieveUserdata();
some code here...

function retrieveUserData() {

$http({ url: "/xx/xx/xxx/" + id,                   // 1st $http call
        method: "GET"
    }).success(function (data, status, headers, config) {
        retval1 = data.Data;
        retrieveUserCombos();
    });
};


function retrieveUserCombos() {
        $http({ url: "/xx/xx/xxx/" + id,             // 2nd $http call to populate combobox according to user's characteristics  
             method: "GET"
         }).success(function (data, status, headers, config) {
            retval2 = data.Data;
            retrieveSomethingElseThatDependsOnTheUserCombos();
            });
         }

};

function retrieveSomethingElseThatDependsOnTheUserCombos(){
     $http({ url: "/xx/xx/xxx/" + id,             // 3nd $http call to do something  
             method: "GET"
         }).success(function (data, status, headers, config) {
            some code here...
            });
         }
};

in the example above, the function "retrieveUserdata" does a lot more that just retrieving some user data.

what I'd like to have is:

some code here...
retrieveUserdata();
retrieveUserCombos();
retrieveSomethingElseThatDependsOnTheUserCombos();
some code here...

how can I do that, please?

thanks.
Reply all
Reply to author
Forward
0 new messages