简体   繁体   中英

Promises in AngularJS

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.

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 .

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

$.ajax({
  dataType: "json",
  url: url,
}).done( function(json) {
  j = json;
});

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
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM