【问题标题】:done() method on Promises/A+ specification usage in AngularAngular 中 Promises/A+ 规范使用的 done() 方法
【发布时间】:2015-06-20 03:07:41
【问题描述】:

Here 建议使用 done 方法结束 Promise 链,以便重新抛出错误:

done 与 then 用法的黄金法则是:要么返回你的承诺 给其他人,或者如果链以你结束,调用 done 终止 它。用 catch 终止是不够的,因为 catch 处理程序 本身可能会引发错误。

它适用于 AngularJs 吗?我看了看,框架里好像没有这样的方法。

更新:

我查看了代码,发现如下:

try {
    if (isFunction(fn)) {
        promise.resolve(fn(state.value));
    } else if (state.status === 1) {
        promise.resolve(state.value);
    } else {
        promise.reject(state.value);
    }
} catch (e) {
    promise.reject(e);
    exceptionHandler(e);
}

window.onerror = function(e) {
    // doesn't come here
}

所以基本上 Angular 还会在 exceptionHandler(e); 中记录来自承诺处理程序的错误,因此它不会被忽视。如果需要,可以按照 here 的说明覆盖默认 exceptionHandler 的行为。

【问题讨论】:

    标签: javascript angularjs promise angular-promise


    【解决方案1】:

    Promises/A+ 规范上的done() 方法

    请注意,Promises 仅指定 then,而没有提及 done

    Q recommends to... Angular 中的用法呢?

    Q 不是$q! Angular 的 promise 实现中没有 done 方法,所以我建议不要使用它。

    Q 的黄金法则不适用于 Angular,它们有很大不同的功能。


    Promises 是异步的,因此您不能在回调周围使用try catch 语句。 done 用于向环境抛出不可恢复、不可捕获的内容(因此将调用 window.onerrorprocess.onuncaughtexception)。

    如果你想捕捉异常,你应该使用带有回调的catch方法:

    $q.reject(new Error()).catch(function(e) {
        console.log("does catch an error"); 
    });
    

    要捕获未处理的拒绝(在您的承诺链的末尾),您还可以使用$exceptionHandler

    【讨论】:

    • 谢谢,所以没有办法像我在更新中显示的那样捕获catch 处理程序中抛出的错误?而且由于 Angular 的 $exceptionHandler 捕获了在 Promise 中抛出的错误(根据规范,这些错误在 Promise 中被使用),所以这个错误不会被忽视,对吧?
    • 是的,我的例子是无效的,对不起,没有想通。这个想法是,如果在回调c 这里.catch(c) 中发生异常,没有done(),根据Q 的文档,这个异常将不会在非角度应用程序中报告,并且不会被注意到,对吧?
    • @Maximus:是的,它只会拒绝返回的承诺。这可能会或可能不会被忽视(仅在承诺链的末尾)。
    • 对,所以在 Angular 世界中,它总是会被注意到(不需要 done() 方法),因为它在 digest 循环中被评估,$exceptionHandler 可以把它捡起来吗?
    • 是的,你是对的,我将删除该行。如果需要,我可以覆盖默认的exceptionHandler 以重新抛出,如here 所述。我通常不会使用第二个 catch(),因为我通常不会期望在 failure 回调中被拒绝。
    【解决方案2】:

    Angular 使用 $q 是:

    受 Kris Kowal 的 Q 启发的承诺/延迟对象的实现。

    您需要使用 Angular 文档中提供的 the Promise API:.finally()、.then() 和 .catch()。

    Angular 很好地描述了这种差异:

    Q 比 $q 有更多的功能,但这是以字节为代价的。 $q 很小,但包含常见异步任务所需的所有重要功能。

    所以看起来 $q 中没有 .done()。

    希望它能回答你的问题。

    【讨论】:

      【解决方案3】:

      除了 sebastienbarbier 的回答之外,$q 角度服务还绑定到 $digest 循环(角度在内部运行)并且(对于 $q)执行 Kris Kowal 的 Q 中的 .done() 功能。

      这可以让你在测试中脱颖而出,其中 $scope.digest() 可确保完全解决承诺。

      【讨论】:

        猜你喜欢
        • 2016-07-11
        • 1970-01-01
        • 1970-01-01
        • 2018-10-10
        • 2017-10-30
        • 1970-01-01
        • 2018-11-07
        • 2015-06-08
        • 1970-01-01
        相关资源
        最近更新 更多