在不触发成功回调的情况下捕获 $q 服务中的拒绝

catch rejection in $q service without triggering success callbacks

我有一个 return 是 $q (Q) 承诺的方法:

var subtypesMetadataResolved = restService.getNodeSubtypesMetadata();

现在,当元数据可用时,我想 运行 两个函数来处理它们。首先,我想像这样链接它们:

subtypesMetadataResolved.then(createNodes).then(prepareDataForWidgets)

但后来我意识到,因为它们都需要由 subtypesMetadataResolved 承诺 return 编辑的数据,所以我需要 return 这些数据也来自 createNodes 成功回调,以便它被传递到 prepareDataForWidgets,这不是一个选项。然后我就这样做了:

subtypesMetadataResolved.then(createNodes)
subtypesMetadataResolved.then(prepareDataForWidgets)

这符合我的需要。但现在的问题是如何在 subtypesMetadataResolved 被拒绝时调用我的 rejection 回调,并且在这种情况下既不触发 createNodes 也不触发 prepareDataForWidgets 回调?我有以下内容,但在触发 nodeSubtypesMetadataErrorCb 之后它还会触发 createNodes 回调:

subtypesMetadataResolved.catch(nodeSubtypesMetadataErrorCb);
subtypesMetadataResolved.then(createNodes)
subtypesMetadataResolved.then(prepareDataForWidgets)

我是这样拒绝的subtypesMetadataResolved:

编辑:

function getNodeSubtypesMetadata(subtype) {
    return $q.when("success!").then(function(){
        debugger
        throw new Error();
    });
}

var subtypesMetadataResolved = getNodeSubtypesMetadata();
subtypesMetadataResolved.then(successCb1);
subtypesMetadataResolved.then(successCb2);
subtypesMetadataResolved.catch(nodeSubtypesMetadataErrorCb);

$q.all([
    typesMetadataResolved,
    subtypesMetadataResolved
]).then(init);

问题是您将带有 handled 错误的承诺分配给 subtypesMetadataResolved。如果您对此调用 .then(),它 调用 then() 回调,因为 .catch() 回调本质上是 "handling" 错误。

要解决这个问题,请将 unhandled 承诺分配给您的变量,然后调用 .catch()/.then()

var subtypesMetadataResolved = getNodeSubtypesMetadata();

subtypesMetadataResolved.catch(nodeSubtypesMetadataErrorCb);
subtypesMetadataResolved.then(function(){
    debugger
});
subtypesMetadataResolved.then(function () {
    debugger
});

作为风格问题,我建议将 catch 行放在 then 行之后,但这对代码的行为应该没有明显的影响。

查看这行代码:

getNodeSubtypesMetadata().catch(nodeSubtypesMetadataErrorCb)

有两个承诺。第一个是 getNodeSubtypesMetadata() 返回的承诺,它被拒绝了。第二个承诺由 catch(nodeSubtypesMetadataErrorCb) 返回,它已实现。因此,当您将上述表达式的结果分配给一个变量时,您将获得第二个已实现的承诺。由于您对第一个承诺感兴趣,因此需要将代码更改为:

var subtypesMetadataResolved = getNodeSubtypesMetadata();
subtypesMetadataResolved.catch(nodeSubtypesMetadataErrorCb);
subtypesMetadataResolved.then(function(){
    debugger
});
subtypesMetadataResolved.then(function () {
    debugger
});

编辑: 作为替代方案,要让两个函数都作用于同一个已实现的承诺,您可以只用一个函数包装它们:

function nodeSubtypesMetadataFulfilledCb(metadata) {
    createNodes(metadata);
    prepareDataForWidgets(metadata);
}

subtypesMetadataResolved.then(
    nodeSubtypesMetadataFulfilledCb,
    nodeSubtypesMetadataErrorCb);