30

I have the following scenario, I need data from a particular url. I have written a function which takes parameter 'url'. Inside the function I have the $http.get method which makes a call to the url. The data is to be returned to the calling function

var getData = function (url) {
    var data = "";

    $http.get(url)
        .success( function(response, status, headers, config) {
             data = response;
        })
        .error(function(errResp) {
             console.log("error fetching url");
        });
    return data;
}

The problem is as follows, $http.get is asynchronous, before the response is fetched, the function returns. Therefore the calling function gets the data as empty string. How do I force the function not to return until the data has been fetched from the url?

1
  • 1
    You may return success and error function itself which can be used further... Commented Jul 20, 2015 at 5:43

4 Answers 4

23

Take a look at promises to overcome such issues, because they are used all over the place, in angular world.

You need to use $q

var getData = function (url) {
    var data = "";
    var deferred = $q.defer();

    $http.get(url)
        .success( function(response, status, headers, config) {
             deferred.resolve(response);
        })
        .error(function(errResp) {
             deferred.reject({ message: "Really bad" });
        });
    return deferred.promise;
}

Here's a nice article on promises and $q

UPDATE:

FYI, $http service itself returns a promise, so $q is not necessarily required in this scenario(and hence an anti-pattern).

But do not let this be the reason to skip reading about $q and promises.

So the above code is equivalent to following:

var getData = function (url) {
    var data = "";
    return $http.get(url);
}
Sign up to request clarification or add additional context in comments.

7 Comments

how do I access the value of the promise?
Yes I know. But I tried to keep things simple for OP. A statement like "$http itself returns a promise" could confuse anyone if one is not aware of what promises are on the first hand.
Why is this answer marked as correct? This solutions does not make the http request synchronous, it is still asynchronous.
@CarlosCalla: Did I mention this is a 'synchronous' technique at any place in my solution? You probably just read the question title but didn't see OP's actual requirement. In case you missed it, here's the gist to his problem. OP is actually returning something from the function, whose value is indeed inferred "async". See how do I force the function not to return until the data has been fetched from the url part. Solution to this problem is NOT making the code synchronous. Hence I mentioned 'promises' in answer.
|
9

You can use $q.all() method also to solve this problem

var requestPromise = [];

var getData = function (url) {
    var data = "";

    var httpPromise = $http.get(url)
        .success( function(response, status, headers, config) {
             data = response;
        })
        .error(function(errResp) {
             console.log("error fetching url");
        });

    requestPromise.push(httpPromise);
}

in the calling function

$q.all(requestPromise).then(function(data) {

    //this is entered only after http.get is successful
});

make sure to inject $q as a dependency. Hope it helps

Comments

8

You function seems redundant. Just use $http.get(url), since you aren't really doing anything else before you use it anyway.

var url = 'foo/bar';

$http
    .get(url)
    .success( function(response, status, headers, config) {
        $scope.data = response;
    })
    .error(function(errResp) {
        console.log("error fetching url");
    });

Or if you need to access the promise later just assign it to variable;

var promise = $http.get(url);

// some other code..

promise.then(function(data){
   //.. do something with data
});

Comments

4

A typical way to do what you want is like so:

var getData = function(url, callback) {
    $http.get(url).success(function(response) {
        callback && callback(response);
    });
};

Used like:

getData('/endpoint', function(data) {
    console.log(data);
});

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.