AngularJS中带有Promise的$ http-calls的条件链接

时间:2015-05-05 15:06:08

标签: javascript angularjs angular-promise

我必须按顺序执行三个不同的$ http-calls,它们相互依赖。到目前为止,我的工作解决方案是这样的

$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-calls的propper函数,这可以减少。但据我所知,更好的解决方案是正确使用和链接$ http-promises,如下所示:

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

});

但现在我的问题是,我怎样才能以最少的代码复制来跳过第一次调用?

3 个答案:

答案 0 :(得分:10)

您可以尝试这种方法:

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

答案 1 :(得分:4)

您可以将$http.get调用包装在测试条件的函数中,如果条件适用则返回$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/...");
})

答案 2 :(得分:1)

我希望能够看到这样的东西工作,所以我把这个小控制器放在一起演示了解决的promises,首先运行条件$ 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
    })
    })
    })
  }
});