0

In Angular (and other JavaScript frameworks), data from an http request is retrieved async using a promise and can be set to a variable using a callback. Simple enough. But I'm getting tired of writing code that looks like this:

service.getWidgetsAsync(function (result) { vm.widgets = result.data });

Is there any way that I haven't thought of to write the above more like this....?

vm.widgets = service.getWidgetsAsync();

"No" is probably a valid answer. :-)

(Example of the getWidgetsAsync added to clarify: )

function getWidgetsAsync(callback) {
    $http.get(APPBASEURL + 'Foo/GetWidgets')
        .then(function(result) {
            callback(result);
        });
}
4
  • 1
    I don't see any promises in your example. A callback function is basically the antithesis of a promise. Commented Oct 2, 2014 at 18:02
  • My understanding is 'getWidgetsAsync' is the promise, with a callback being passed into it. Commented Oct 2, 2014 at 18:03
  • 1
    Are you conflating "promise" with "asynchronous function"? Promises have a .then() method. You don't call them directly as functions. Could you name an actual API that you're using instead of a fake name like "getWidgetsAsync"? Then we can find out if it has anything to do with promises. Commented Oct 2, 2014 at 18:05
  • 1
    If you want to use async, you need a callback that runs when it's done. Whether you inline that callback or use a promise is up to you, but it has to be one or the other. Commented Oct 2, 2014 at 18:06

2 Answers 2

2

The problem is that you are defeating the whole point of promises by involving callbacks. Return the promise instead of using it to call a callback:

function getWidgetsAsync() {
    return $http.get(APPBASEURL + 'Foo/GetWidgets');
}

Then you can write code like this:

service.getWidgetsAsync()
.then(function (result) {
    vm.widgets = result.data;
    // do more stuff with vm.widgets
})
.then(/* do other things after the function above is done */);

The answer to your question is no, you can't use the result of an asynchronous operation immediately after you call it. If you could, it wouldn't be asynchronous.

Sign up to request clarification or add additional context in comments.

1 Comment

Not sure why I hadn't thought to return/expose the promise from the $http.get.... This was helpful, thanks!
1

Yes and no... You can use angular $resource which will initially populate the variable with an empty object and fill in the details when it gets the results so your code will look like you want, but the values aren't filled in until the call completes so you can't immediately assume you have data.

angular.module('MyApp')
    .factory('WidgetResource', ['$resource', function ($resource) {
        return $resource('/api/widgets',
          { 
            'get':    {method:'GET'},
            'save':   {method:'POST'},
            'query':  {method:'GET', isArray:true},
            'remove': {method:'DELETE'},
            'delete': {method:'DELETE'}
          });
    }]);

Then in your controller:

var vm.widgets = WidgetResource.query();

Any bindings or watches you do will fire when the data is received. For instance if you have a list of widgets in an ng-repeat they will show up when the ajax call completes, but if you check the length of the widgets array immediately after the line above in your code it will be zero.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.