Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AngularJS - fail resilence on $q.all()

I'm trying to fill some local data resolving a series of remote calls.
When every promise is resolved, I load the data and proceed.

The method $q.all( [] ) does exactly this:

        $q.all([
            this.getUserInfo(11)
                .then(function (r) {
                    results.push(r)
                }),

            this.getUserConns()
                .then(function (r) {
                    results.push(r)
                }),

            this.getUserCtxs()
                .then(function (r) {
                    results.push(r)
                })
        ])
        .then(function () {
            console.log(results)
        })


Problem is, this code is not resilient.
If any of these call fails, nobody gets the fish!

Wrapping the calls in a try/catch statement, simply causes $q.all() to entirely ignore the entry, even when not failing (note the console.log in the func)...

        $q.all([
            this.getUserInfo2(11)
                .then(function (r) {
                    results.push(r)
                }),

            function () {
                try {
                    this.getUserGroups()
                        .then(function (r) {
                            console.log(r)
                            results.push(r)
                        })
                }
                catch (err) {
                    console.log(err)
                }
            },
        ])
        .then(function () {
            console.log(results)
        })

Output:

[Object]


Any hint on how I could wrap this to be resilient?


Thanks to @dtabuenc, I've gone one step further. Implementing the error callback, I can avoid the breaking of the chain, and push the values of the resolved promises.

However, a nasty Exception is still displayed on the console... How can I get rid of that if I cannot try/catch on async requests?

Caller code

    return $q.all([

            this.getUserInfo(user_id)
                .then(function (r) {
                    results['personal_details'] = r
                }),

            this.getUserConns()
                .then(
                    function (r) {
                    results['connections'] = r
                    },
                    function(err) {
                        console.log(err)
                    })

        ])
        .then(function () {
            return (results)
        })

Callee code (inject with an exception)

    getUserConns: function() {

        return __doCall( ws.getUserConnections, {} )
            .then( function(r) {

                // very generic exception injected
                throw new Error

                if (r && r.data['return_code'] === 0) {
                    return r.data['entries']
                }
                else {
                    console.log('unable to retrieve the activity - err: '+r.data['return_code'])
                    return null
                }
            })
    },
like image 706
domokun Avatar asked Dec 13 '13 09:12

domokun


People also ask

What is Q defer () in AngularJS?

Simply put you can use $q. defer() to create a Promise. A Promise is a function that returns a single value or error in the future. So whenever you have some asynchronous process that should return a value or an error, you can use $q. defer() to create a new Promise.

What does $q do in AngularJS?

$q is an angular defined service. It's the same as new Promise(). But $q takes things to the next level by enhancing additional feature that developers can use to perform complex tasks more simply. resolve(value) – resolves the derived promise with the value.

What does Promise return in angular?

What Is Promise in Angular? Promises in Angular provide an easy way to execute asynchronous functions that use callbacks, while emitting and completing (resolving or rejecting) one value at a time. When using an Angular Promise, you are enabled to emit a single event from the API.


1 Answers

This will work but also push the errors to the array.

function push(r) {
    results.push(r);
}

$q.all([
    this.getUserInfo(11).then(push).catch(push),
    this.getUserConns().then(push).catch(push),
    this.getUserCtxs().then(push).catch(push)
])
.then(function () {
    console.log(results);
})

You should also improve your understanding of promises, you never should use try-catch with promises - when using promises, you use the .catch() method (with everything else being implicitly a try). This works for normal errors as well as asynchronous errors.


If you want to totally ignore the errors:

function push(r) {
    results.push(r);
}

function noop() {}

$q.all([
    this.getUserInfo(11).then(push).catch(noop),
    this.getUserConns().then(push).catch(noop),
    this.getUserCtxs().then(push).catch(noop)
])
.then(function () {
    console.log(results);
})
like image 152
Esailija Avatar answered Oct 07 '22 17:10

Esailija