Angular 的 $q.reject() 与 deferred.reject()

Posted

技术标签:

【中文标题】Angular 的 $q.reject() 与 deferred.reject()【英文标题】:Angular's $q.reject() vs deferred.reject() 【发布时间】:2014-08-18 02:04:06 【问题描述】:

我正在尝试处理 Angular $q 服务及其相关对象和 API。当我查看控制台中的对象时,我看到:

var deferred = $q.defer()

...(and then from console inspection)...

$q: Object defer: function, reject: function, when: function, all: function

deferred: Object resolve: function, reject: function, notify: function, promise: Object

deferred.promise: Object then: function, catch: function, finally: function

它提出了几个问题:

    $q.reject()deferred.reject() 有什么区别?何时使用? deferred.promise.then(successFn, errorFn)中的errorFndeferred.promise.catch(catchFn)中的catchFn是什么关系? 如果我有一堆嵌套的 Promise 并且发生错误,是否会始终调用最外层的 catch() 函数?如果其中一个嵌套的 Promise 也定义了一个 catch 函数怎么办?这个 catch 会阻止最外层的 catch 执行吗?

谢谢。

【问题讨论】:

【参考方案1】:

1)$q.reject()是创建deferred然后立即reject的快捷方式;如果我无法处理错误,我经常在 errorFn 中使用它。

2) 没什么,promise.catch(errorFn) 只是promise.then(null, errorFn) 的语法糖,就像$http 服务的成功和错误方法一样,所以你可以编写如下代码:

promise.
    then(function(result)
        // handle success
        return result;
    , function errorHandler1(error)
        // handle error, exactly as if this was a separate catch in the chain.

    ).catch(function errorHandler2(error)
        // handle errors from errorHandler1
    );

3) 这正是 $q.reject 可以派上用场的地方:

promise.
    catch(function(error)
       //Decide you can't handle the error
       return $q.reject(error); //This forwards the error to the next error handler;
    ).catch(function(error)
       // Here you may handle the error or reject it again.
       return 'An error occurred'; 
       //Now other errorFn in the promise chain won't be called, 
       // but the successFn calls will.
    ).catch(function(error)
       // This will never be called because the previous catch handles all errors.
    ).then(function(result)
       //This will always be called with either the result of promise if it was successful, or 
       //'An error occured' if it wasn't
    );

【讨论】:

感谢您的简洁回答。他们非常清楚。尽管如此,仍然停留在#2上。假设您的示例代码在调用 then() 时同时提供了 successFn 和 errorFn。现在 catchFn 会在什么情况下运行? 我将答案更新为 2)。 catch 方法与 then 函数的第二个参数完全相同。 promise.catch(errorFn) 与 promise.then(null, errorFn) 相同。 如果有人想进一步了解何时使用$q,我发现这篇文章很有帮助codelord.net/2015/09/24/$q-dot-defer-youre-doing-it-wrong【参考方案2】:

好的,这是我的承诺。

    $q.reject(reason) 返回一个被拒绝的承诺,原因是作为参数传递并延迟。 Reject 拒绝存在的延迟,无论其过程是否完成。

    errorFn 在 promise 被拒绝并且它的参数是它被拒绝的原因时启动。当 Promise 过程中的错误未正确处理导致 Promise 引发和异常并且未被拒绝或履行时,将调用 Catch。

    你不应该有嵌套的 Promise,你应该有链式的 Promise,在这种情况下,如果没有指定其他块来处理最新的 catch 块,则应该捕获它之前的所有内容。

【讨论】:

对于#2,你看到我是在我的 successFn 还是 errorFn 中并且我执行 throw new Error(...) 然后 catchFn 会运行吗?我的理解是事实并非如此。 可以在处理程序中,也可以在进程中。在这个过程中它肯定会捕获,但我认为处理程序也是 问题是在这个过程中可能会发生错误,这可能会阻止承诺转换到任何状态,因此 catch 块用于检测这些错误,例如,如果您的进程执行除法并且您尝试要除以 0,您将引发一个异常,如果未缓存和处理,该异常将自动退出进程。 catch 块将得到它并相应地采取行动。也许我会回答我的问题,因为我认为这是正确的行为

以上是关于Angular 的 $q.reject() 与 deferred.reject()的主要内容,如果未能解决你的问题,请参考以下文章

将 TypeMoq 模拟与 Angular TestBed 一起使用

无法运行 Angular 站点,因为我的 angular.json 文件路径与 ng build 创建的不匹配

如何返回一个失败的承诺?

@angular/material/index.d.ts' 不是模块

node_modules/@angular/material/table/cell.d.ts 中的错误 -Typescript 版本问题 angular

Angular 1.3.x 有 .d.ts 文件吗?