为什么要将我的$ http调用转换为服务?

目前我有三个控制器都有这样的电话:

$scope.getCurrentUser = function () {
    $http.post("/Account/CurrentUser", {}, postOptions)
        .then(function(data) {
                var result = angular.fromJson(data.data);
                if (result != null) {
                    $scope.currentUser = result.id;
                }
            },
            function(data) {
                alert("Browser failed to get current user.");
            });
};

我看到很多建议把$http调用封装到一个HttpService中,或者其他一些方法,但是返回promise比返回数据更好。 然而,如果我回复承诺,我的控制器$http所有行都会改变,并且处理响应的所有逻辑都保留在我的控制器中,例如:

$scope.getCurrentUser = function() {
    RestService.post("/Account/CurrentUser", {}, postOptions)
        .then(function(data) {
                var result = angular.fromJson(data.data);
                if (result != null) {
                    $scope.currentUser = result.id;
                }
            },
            function(data) {
                alert("Browser failed to get current user.");
            });
};

我可以为每个服务器端控制器创建RestService,但最终只会调用核心服务并传递URL。


在非平凡的应用程序中,这是良好实践的几个原因。

使用单个通用服务并传递url和参数并不会增加您注意到的那么多的价值。 相反,您需要为每种类型的提取获取一种方法。

使用服务的一些好处:

  • 重用性 。 在一个简单的应用程序中,每个控制器可能有一个数据提取。 但这很快就会改变。 例如,您可能有一个包含getProducts的产品列表页面,以及一个包含getProductDetail的详细信息页面。 但是,您希望在详细信息页面上添加销售页面,类别页面或显示相关产品。 这些可能都使用原始的getProducts(使用适当的参数)。
  • 测试 。 您希望能够独立于外部数据源来测试控制器。 将数据烘焙到控制器中并不容易。 使用服务,您只需嘲笑该服务,并且可以使用稳定的已知数据测试控制器。
  • 可维护性 。 您可以决定使用简单的服务,即使您重复使用它,也可以将其全部放入控制器中,这是相似的代码量。 如果后端路径改变会发生什么? 现在您需要在使用它的任何地方更新它。 如果需要一些额外的逻辑来处理数据,或者需要通过另一个调用获得一些补充数据,会发生什么? 通过服务,您可以在一个地方进行更改。 随着它被烘烤到控制器中,你有更多的工作要做。
  • 代码清晰 。 你想让你的方法去做清楚的,具体的事情。 控制器负责应用程序特定部分的逻辑。 添加获取数据的机制混淆了这一点。 用一个简单的例子,你需要的唯一额外逻辑就是解码json。 如果您的后端完全以完全正确的格式返回您的控制器所需的数据,那还不错,但情况可能并非如此。 通过分解代码,每种方法都可以很好地完成一件事。 让服务获取数据并以恰当的格式将其传递给控制器​​,然后让控制器执行此操作。

  • 一个控制器执行表示逻辑(它在Angular Model-View-Whatever模式中充当一个视图模型)。 服务做商业逻辑(模型)。 这是经过战斗证明的问题与OOP良好做法固有部分的分离。

    瘦控制器和胖服务保证应用程序单位保持可重用,可测试和可维护。

    如果它们是相同的东西,用RestService替换$http没有任何好处。 业务和表示逻辑的正确分离预计会是这样的

    $scope.getCurrentUser = function() {
      return UserService.getCurrent()
      .then(function(user) {
        $scope.currentUser = user.id;
      })
      .catch(function(err) {
        alert("Browser failed to get current user.");
        throw err;
      });
    });
    

    它负责结果调节并返回一个承诺。 getCurrentUser传递一个promise,所以它可以被链接(如果需要)(通过其他控制器方法或测试)。


    让你的服务看起来像这样是有道理的:

    app.factory('AccountService', function($http) {
        return {
            getCurrentUser: function(param1, param2) {
                var postOptions = {}; // build the postOptions based on params here
                return $http.post("/Account/CurrentUser", {}, postOptions)
                .then(function(response) {
                  // do some common processing here
                });
            }
        };
    });
    

    然后调用这个方法看起来就是这样的:

    $scope.getCurrentUser = function() {
        AccountService.getCurrentUser(param1, param2)
        .then(function(currentUser){
            // do your stuff here
        });
    };
    

    这看起来好多了,并且可以避免在多个控制器中重复使用后端服务url和postOptions变量构造。

    链接地址: http://www.djcxy.com/p/92103.html

    上一篇: Why move my $http calls into a service?

    下一篇: Get Data APDU command different tags and response format