0

I try to load json file with angularjs, $q and return data from angular filter.

I have a angular filter:

MyApp.filter('my_filter', function ($q){
    return function(input){
        var deferred = $q.defer();
        var j = {};

        $.getJSON(url, function(json) {
            j = json;
            deferred.resolve(json);
        });

        return j;

But i got {}. How can i synchronously load json and return it's content from filter?

Thank you.

Benjamin Gruenbaum
  • 270,886
  • 87
  • 504
  • 504
0xAX
  • 20,957
  • 26
  • 117
  • 206

3 Answers3

3

You can do this synchronously

AngularJS uses jqLite, you can create a normal GET request with .ajax and pass it an async:false flag just like in jQuery. One way to make all your AJAX synchronous would be:

$.ajaxSetup({async:false});

You can also do this in the options section of any request.

But you shouldn't

Really, AJAX is asynchronous by design, JavaScript thrives on performing async i/o it's why it's an awesome language. If you perform synchronous ajax the screen will freeze until the AJAX will arrive which will create a very bad user experience.

What I'd do is return a promise from the AJAX performing method, when it resolves have it update another scope variable, and filter that instead. Better yet, you can write the code above as:

 return $.getJSON(url);

Avoid the deferred altogether. Using that deferred is called the deferred anti-pattern.

Community
  • 1
  • 1
Benjamin Gruenbaum
  • 270,886
  • 87
  • 504
  • 504
0

getJSON works async. I suggest you to use ajax instead.

$.ajax({
  dataType: "json",
  url: url,
}).done( function(json) {
  j = json;
});
Kasyx
  • 3,170
  • 21
  • 32
0

You should return the promise that is reside inside the deferred object. What you need to do is replace your return code with:

return deferred.promise;

Explanation: Promises are a very good way to handle async code. What you like to do is return to the calling function a promise that say something like "I give you this promise that when my callback function will return I return a result" and when the callback is executed later on you should (and actually rightfully do) resolve the deferred with the data you like to return. This resolve call activate the "then" function that is chained to the promise you have returned.

On the receiving function you should "wait" on the promise to be resolved, something like:

functionThatReturnPromise()
.then(function(result){
    //This is a handler function that called when you call "**deferred.resolve(json)**" so **result** object will hold the **json** object.
...})
.then(function(result){
    //Here you can chain promises as much as you want because "**then**" return the same promise.
})
.catch(function(err){
    //If instead of "**deferred.resolve(json)**" you will call "**deferred.reject(someErr)**" you will end up in this handler function
}
Kfir Erez
  • 3,280
  • 2
  • 18
  • 17