简体   繁体   English

Angular - 在promise链的第一个函数中处理$ q中的异常

[英]Angular - Handling exceptions in $q in the first function of a promise chain

Consider the following code: 请考虑以下代码:

// Fiddle - http://jsfiddle.net/EFpn8/3/
f1().then(function(data) {
                console.log("success 1: "+data)
                return f2();
            })
            .then(function(data) {console.log("success 2: "+data)})
            .catch(function(data) {console.log("error: "+data)});

function f1() {
    var deferred = $q.defer();
    // An exception thrown here is not caught in catch
    // throw "err";
    deferred.resolve("done f1");        
    return deferred.promise;
}

function f2() {
    var deferred = $q.defer();
    // An exception thrown here is handled properly
    // throw "err";
    deferred.resolve("done f2");        
    return deferred.promise;
}    

If the following code runs with an exception in f2 , then the catch function is called correctly. 如果以下代码在f2中运行异常,则正确调用catch函数。 However, in case there is an exception in f1 then the catch code never executes and only a standard JS exception occurs. 但是,如果f1中存在异常,则catch代码永远不会执行,只会发生标准的JS异常。

In the original Q library, this could be handled by this code: 在原始Q库中,这可以通过以下代码处理:

    // Fiddle - http://jsfiddle.net/FEPc7/
    Q.fcall(f1).then(function(data) {
        console.log("success 1: "+data)
        return f2();
    })
    .then(function(data) {console.log("success 2: "+data)})
    .catch(function(data) {console.log("error: "+data)});

Using fcall the f1 function is safely guarded and an exception in it will trigger the catch function as expected. 使用fcall可以安全地保护f1函数,并且其中的异常将按预期触发catch函数。

Since it seems to be that the same behavior from all members of a promise chain would be helpful and natural to the developer, I made the following function for AngularJS: 由于似乎承诺链的所有成员的相同行为对开发人员来说是有用和自然的,因此我为AngularJS创建了以下函数:

// Fiddle - http://jsfiddle.net/EFpn8/5/
function promise(work) {
    var deferred = $q.defer();
    try {
        deferred.resolve(work());
    } catch(err) {
        deferred.reject(err);
        throw err;
    }
    return deferred.promise;        
}

Which can be used like so: 哪个可以这样使用:

promise(f1).then(function(data) {
                console.log("success 1: "+data)
                return f2();
            })
            .then(function(data) {console.log("success 2: "+data)})
            .catch(function(data) {console.log("error: "+data)});

This works fine, however, it seems rather a hack. 这很好,但是,它似乎是一个黑客。 Is there something inherit in Angular to do that instead? 在Angular中有继承的东西吗? Or is it unnecessary for some reason? 或者由于某种原因它是不必要的?

The first call of the chain is synchronous, so at first glance it seems unusual for exceptions raised in it to be then passed to $q to then call the error callbacks, which are for the asynchronous promise rejections (or indeed exceptions) 链的第一次调用是同步的,所以乍一看似乎异常,然后将其中引发的异常传递给$q ,然后调用错误回调,这是针对异步承诺拒绝(或实际上是异常)

To quote from the $q docs 引用$ q文档

Q has many more features than $q Q有比q更多的功能

So the lack of fCall function sounds like one of the things the team decided could be removed. 因此缺乏fCall功能听起来像团队决定可以删除的东西之一。 It looks like you do have to roll your own, like you have. 看起来你必须像你一样自己滚动。 You might want to use a technique like from https://gist.github.com/leon/8800809 to decorate $q with a fCall method, so you then use it like: 您可能希望使用https://gist.github.com/leon/8800809之类的技术来使用fCall方法来装饰$q ,因此您可以使用它:

$q.fCall(f1).then(function()...

I know this is an older question, but I hit the same thing today and found this answer but didn't think I should need to add fCall() to get this to work. 我知道这是一个较老的问题,但我今天也遇到了同样的问题并找到了答案,但我认为我不需要添加fCall()来实现这一点。 After a little digging I found this can be done in Angular v1.5 today (not sure at what point this became valid): 经过一番挖掘后,我发现今天可以在Angular v1.5中完成(不知道这在什么时候变得有效):

$q.when().then(() => f1)...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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