AngularJS - $q.all() 上的失败恢复 [英] AngularJS - fail resilence on $q.all()

查看:25
本文介绍了AngularJS - $q.all() 上的失败恢复的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试填充一些本地数据以解决一系列远程调用.
当每个承诺都得到解决时,我加载数据并继续.

方法 $q.all( [] ) 正是这样做的:

 $q.all([this.getUserInfo(11).then(函数(r){结果.push(r)}),this.getUserConns().then(函数(r){结果.push(r)}),this.getUserCtxs().then(函数(r){结果.push(r)})]).then(函数(){控制台日志(结果)})


问题是,这段代码没有弹性.
如果这些调用中的任何一个失败,没有人会得到鱼!

将调用包装在 try/catch 语句中,只会导致 $q.all() 完全忽略该条目,即使没有失败(注意 func 中的 console.log)..

 $q.all([this.getUserInfo2(11).then(函数(r){结果.push(r)}),功能 () {尝试 {this.getUserGroups().then(函数(r){控制台.log(r)结果.push(r)})}抓住(错误){控制台日志(错误)}},]).then(函数(){控制台日志(结果)})

输出:

<块引用><块引用>

[对象]


关于如何包装它以具有弹性的任何提示?<小时>感谢@dtabuenc,我更进了一步.实现错误回调,我可以避免断链,并推送已解决的承诺的值.

然而,一个讨厌的异常仍然显示在控制台上......如果我无法尝试/捕捉异步请求,我该如何摆脱这种情况?

来电者代码

 return $q.all([this.getUserInfo(user_id).then(函数(r){结果['personal_details'] = r}),this.getUserConns().然后(功能(r){结果['连接'] = r},功能(错误){控制台日志(错误)})]).then(函数(){返回(结果)})

被调用者代码(注入异常)

 getUserConns: function() {返回 __doCall( ws.getUserConnections, {} ).then(函数(r){//非常通用的异常注入抛出新错误if (r && r.data['return_code'] === 0) {返回 r.data['entries']}别的 {console.log('无法检索活动 - 错误:'+r.data['return_code'])返回空值}})},

解决方案

这会起作用,但也会将错误推送到数组.

function push(r) {结果.push(r);}$q.all([this.getUserInfo(11).then(push).catch(push),this.getUserConns().then(push).catch(push),this.getUserCtxs().then(push).catch(push)]).then(函数(){控制台日志(结果);})

<小时>

您还应该提高对 Promise 的理解,永远应该将 try-catch 与 Promise 结合使用 - 使用 Promise 时,您使用 .catch() 方法(其他所有内容都隐式为 try).这适用于正常错误和异步错误.

<小时>

如果你想完全忽略错误:

function push(r) {结果.push(r);}函数 noop() {}$q.all([this.getUserInfo(11).then(push).catch(noop),this.getUserConns().then(push).catch(noop),this.getUserCtxs().then(push).catch(noop)]).then(函数(){控制台日志(结果);})

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
                }
            })
    },

解决方案

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);
})

这篇关于AngularJS - $q.all() 上的失败恢复的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆