AngularJS 中带有 Promise 的 $http 调用的条件链接

Conditional Chaining of $http-calls with Promises in AngularJS

我必须依次执行三个相互依赖的不同 $http 调用。到目前为止,我的工作解决方案是这样的

$http.get(".../1/...").success(function(){
    $http.get(".../2/...").success(function(){
        $http.get(".../3/...").success(function(){

        });
    });
});

现在需要做一些更改:如果条件为真,则应跳过第一次调用。我可以这样做:

if(skipCallOne) {
    $http.get(".../2/...").success(function(){
        $http.get(".../3/...").success(function(){

        });
    });
} else {
    $http.get(".../1/...").success(function(){
        $http.get(".../2/...").success(function(){
            $http.get(".../3/...").success(function(){

            });
        });
    });
}

这显然会导致大量代码复制。我发现如果我对特定的 $http 调用使用适当的函数,这可能会减少。但据我所知,更好的解决方案是正确使用和链接 $http-promises,如下所示:

$http.get(".../1/...").then(function(){
    return $http.get(".../2/...");
}).then(function() {
    return $http.get(".../3/...");
}).then(function() {

});

但现在我的问题是,如何有条件地跳过代码复制最少的第一次调用?

你可以试试这个方法:

$q.when(skipCallOne || $http.get(".../1/..."))
  .then(function() {
    return $http.get(".../2/...");
  }).then(function() {
    return $http.get(".../3/...");
  }).then(function() {
});

您可以将 $http.get 调用包装在测试条件的函数中,并且 return 如果条件适用则 $http.get 承诺或如果条件不适用则包装预先解决的承诺。

function callOne() {
    if(condition) {
        return $http.get(".../1/...");
    } else {
        var deferred = $q.defer();
        deferred.resolve();
        return deferred.promise;
    }
}

callOne().then(function() {
    return $http.get(".../2/...");
})

我希望能够看到这样的东西在工作,所以我将这个小控制器放在一起来演示 promise 解析,首先是有条件的 $http.get 运行。我并不认为这与其他答案一样优雅或聪明,但我认为它与 Cristian 的解决方案非常相似。

注意:可能使这个问题难以理解的一件事是这个问题的答案经常显示 仅执行 的链接 $http 调用,为了简单起见,这些调用返回的值将被忽略,并且可能不会立即清楚如何分解事物以实际获得这些值。

Demo

app.controller('MainCtrl', function($scope, $q, $http) {
  $scope.x = true;

  var firstHttp = function() {
    var deferred = $q.defer()
    if($scope.x) {
      data = 'x was true'
       deferred.resolve(data);
    } else {
      $http.get('test.json')
      .then(function(data) {
        $scope.data1 = data;
        deferred.resolve(data);
      })
    }  
    return deferred.promise
  }

  $scope.myGetterFn = function() {
    firstHttp()
    .then(function(data) 
    {
      data.data ? $scope.data1 = data : $scope.datax = data;
      $http.get('test2.json')
    .then(function(data2) 
    {
        $scope.data2 = data2
        $http.get('test3.json')
    .then(function(data3) 
    {
          $scope.data3 = data3
    })
    })
    })
  }
});