如何将多个 onError 函数分配给一个承诺(由 angular 的 $http.post 返回)

How to assign multiple onError functions to a promise (returned by angular's $http.post)

我的 AngularJS 代码需要将多个 onSuccessonError 函数链接到 $http.post

返回的承诺
  var promise = $http.post(url);
     promise
      .then(
          /*success 1*/function () { console.log("success 1"); },
          /*error 1*/function () { console.log("error 1"); })
      .then(
          /*success 2*/function () { console.log("success 2"); },
          /*error 2*/function () { console.log("error 2"); });

以上代码的问题是当 HTTP 响应失败时它打印 error 1 > success 2 而不是 error 1 > error 2

我对 Whosebug 做了一些研究,发现当你可以访问 $q 时,你可以在 error 1 中执行 $q.reject() 来触发 error 2 但在我的例子中我只能访问 $http.post 返回的承诺。那我该怎么办?

P.S. 当然,我可以从 error 1 内部调用 error2() 但我想将它们链接起来,因为它看起来更可读和可扩展。

有什么想法吗?

只需将处理程序包装在一个函数中,在成功/错误处理程序参数中:

var promise = $http.post(url);
promise
  .then(function(argX, argY){
      success1(argX, argY);
      success2(argX, argY);
  },
  function(argX, argY){
      error1(argX, argY);
      error2(argX, argY);
  });

从 success/error 处理程序返回一个值(或 return 没有值)将解决链中下一个 then 块的承诺。要传播拒绝,return $q.reject():

var promise = $http.post(url);
 promise
  .then(
      /*success 1*/function () { console.log("success 1"); },
      /*error 1*/function () { console.log("error 1"); return $q.reject();})
  .then(
      /*success 2*/function () { console.log("success 2"); },
      /*error 2*/function () { console.log("error 2"); });

你的问题源于对 promises 启用的一些误解 - 即异步代码组合与同步代码的组合与 try/catch 并行,并具有适当的异常处理。

我特指你的说法:

"but i want to chain them because it looks more readable and extensible."

作为链接误解的根源。

如果您的示例是同步的(假设所有异步调用都是阻塞的),这可能是您想要做的:

try {
  var data = $http.post(url); // blocking
  var res1 = doSuccess1(data);
  var ret = doSuccess2(res1);
}
catch(e){
  errorHandler1(e);
  errorHandler2(e);
}

而不是这个:

try {
  try {
    var data = $http.post(url);
    var res1 = doSuccess1(data);
  } catch (e) {
    errorHandler1(e);
    // throw ""; // this is what returning $q.reject would have done - a rethrow
  }
} catch (e) {
    errorHandler2(e);
}
var ret = doSuccess2(res1);

这就是您通过链接可以达到的效果。换句话说,嵌套 try/catchdoSuccess2.

中未处理的异常

以下是第一种方式的异步并行:

var ret;
$http.post(url)
  .then(function(data){
     var res1 = doSuccess1(data);
     ret = doSuccess2(res1);
  }
  .catch(function(e){ // or .then(null, handler)
     doError1(e);
     doError2(e);
  })

如果 doSuccessN 函数之一也是异步的:

var ret;
$http.post(url)
  .then(doSuccess1Async)
  .then(function(res1){
     ret = doSuccess2(res1);
  }
  .catch(function(e){ // or .then(null, handler)
     doError1(e);
     doError2(e);
  })