Angular promises:从 then(...) 语句中触发 catch(...)?

Angular promises: trigger catch(...) from within a then(...) statement?

是否可以从 then(...) 部分中触发承诺链的 catch(...) 部分?

例如,我发出一个 $http 请求并链接一些行为。 $http 成功解析,但在处理数据时,很明显数据更适合错误情况,因此我们想要激活错误处理程序。

问题是——我在两个地方使用了这个承诺链;一个在服务本身中,另一个在激活服务的控制器中。控制器是处理承诺链的 catch(...) 部分的控制器,它会在其中打开一个显示错误消息的模式。

到目前为止,我已经能够将承诺链接起来,这样,无论何时在服务中触发 then(...)catch(...),我都可以 return 结果,并且然后它将在控制器内触发——正如预期的那样。

但是我如何让 then(...) 在服务中触发,但是 return 结果使得 catch(...) 将在控制器中触发?

我尝试使用 $q.reject(...) 创建和 return 一个新的承诺,作为 then(...) 函数中的 return 值,但这似乎没有工作。

示例:

var url = 'http://google.com';
$http.get(url).then(handleFirst).then(handleSecond).catch(error);

function handleFirst (response) {
    console.log("HandleFirstCalled", response);
    return response;
}

function handleSecond (response) {
    console.log("HandleSecondCalled", response);
    return response;
}

function error (response) {
    console.log("ErrorCalled", response);
}

如何获得handleFirst(...),跳过执行handleSecond(...),而是执行error(...)?注意:您不能只调用 error(response),因为无法从外部承诺链访问它。

[编辑:] 找到了解决方案,return $q.reject(response); 确实有效。但是,服务 catch(...) 函数必须始终 return $q.reject(response)。以前,我只有 return response;,它将由 Controller 承诺链继续。但随后控制器将在其链中激活 then(...)

因此 return response; 它变成了:

Service -> $http -> then(...) -> catch(...) -> Controller -> then (...)

通过改变它 return $q.reject(response); 它变成了:

Service -> $http -> then(...) -> catch(...) -> Controller -> catch (...)

您在 Angular 中有两个选项可以拒绝从 then 中返回的承诺。

throw new Error(...); // this will reject the promise and trigger $exceptionHandler

或者:

return $q.reject(new Error(...)); // this will reject the promise

使用第一个表示您无法真正从中恢复的错误,使用后者表示您可以从中恢复的错误。

请注意,在标准(ES6 承诺)和其他兼容承诺(如 Bluebird)中,抛出和拒绝之间没有区别。