【问题标题】:Best way to invoke Rest APIs from angularjs?从 angularjs 调用 Rest API 的最佳方法?
【发布时间】:2013-08-30 09:41:56
【问题描述】:

应该从哪里调用 Angular js 的 REST API 请求?

即从控制器、模块、服务、工厂。我完全不知道什么是正确的方法?

【问题讨论】:

  • 我编辑了我的答案以包括资源使用的要求和示例。

标签: angularjs


【解决方案1】:

以下是我认为的最佳做法:

  • 使用工厂服务来处理访问 RESTful Web api 的机制
  • 将工厂服务注入需要访问的控制器中
  • 在工厂中使用 promise 来解决拒绝来自 $http 调用的响应
  • promise 允许控制器确定它应该如何响应 RESTful 调用的结果。例如,它可能想要调用一个 toast 弹出窗口来通知用户任何问题。

这在数据服务层、业务逻辑和前端 UI 之间保持了良好的分离。它还限制了对任何一层或其他层的更改的任何后果。

【讨论】:

  • 感谢@John Kelleher 的解释......但是当你给出每个例子时会更清楚
【解决方案2】:

您可以使用resources,或构建实现http调用的服务。

如果你想使用资源,请记住:

  1. 包含你可以找到的 angular-resource.js 文件here
  2. 在您的模块声明中包含 ngResource 模块依赖项,如下所示:angular.module('myApp',['ngResource'])

之后你可以用这种方式声明一个资源:

function MyController($scope, $resource){
  var User = $resource('/user/:userId', {userId:'@id'});
  var user = User.get({userId:123}, function() {
    user.abc = true;
    user.$save();
  });
}

或者,如果您需要更深层次的粒度,请使用服务,例如

angular.module('myApp')
.factory('MyAPIService', function($http){
  var apiurl, myData;
  return {
    getData: function(){
      $http.get(apiurl)
      .success(function(data, status, config, headers){
        myData = data;
      })
      .error(function(){ //handler errors here
      });
    },
    data: function() { return myData; }
  };
});

我发现服务很棒,因为它能够在控制器之间共享数据,因此您可以像这样将它们注入控制器中

myapp.controller('MyController', function($scope, MyAPIService){
  $scope.data = MyAPIService.data();
  // etc.

});

【讨论】:

  • 我会选择 Resources,因为它们是为此目的而制作的。
  • @maxdec 是的,资源是为此目的而制作的,但并非所有 API 都是关于对某些对象/模型进行 CRUD 的。还有更复杂的场景需要资源牵强。
  • 我同意,但是当我们谈论的是 RESTful api 并且 REST api 的主要原则是provide access to resources,使用$resource 服务是有意义的:-)跨度>
  • @maxdec 你能给我一个资源的例子吗?
  • 这里是一个简单的例子:masnun.com/2013/08/28/…
【解决方案3】:

我们就是这样做的,将http 服务编写为factory 方法。

根据 cmets 编辑使用Promise API

 var MyApp = angular.module('App', []);

 MyApp .factory('ApiFactory', ['$http',
        function ($http) {
            return {
               getUsers: function (rowcount) {
                var promise = $http.get('api/Users/' + rowcount) .then(function(response) {
                return response.data;
              }, function (error) {
                //error
            })
            return promise;
           }
         }
       }
   ]);

现在您可以像这样在controller 中使用它。

MyApp .controller('MyController', ['$scope', 'ApiFactory',
  function ($scope, ApiFactory) {

    $scope.Users = null;

    ApiFactory.getUsers(count).then(function(data)
    {
      $scope.Users = data;
    });
 } 
 ]);

【讨论】:

  • 我不会将 $http 承诺传递给控制器​​。我更喜欢处理服​​务中的错误(这里是 ApiFactory),然后解决对请求结果的承诺,返回 data.data
  • @b1r3k 感谢您的建议
  • $resource 调用 REST 应该怎么说?
  • @b1r3k 不同意在服务中处理响应错误。当然,捕获错误,但通过将承诺传回控制器,您提供了向用户显示错误通知的机会。从工厂响应前端会引入后端和前端之间的紧密耦合。
  • 此外,从服务传回承诺允许您在控制器中将 API 调用链接在一起,并拥有一个 catch 错误处理程序。一点也不坏的做法 OMHO。保持可测试、分离和整洁。
【解决方案4】:

你可以使用restangularhttps://github.com/mgonto/restangular

你会这样调用你的 api:

// Only stating main route
Restangular.all('accounts')

// Stating main object
Restangular.one('accounts', 1234)

【讨论】:

    【解决方案5】:

    只要你使用 $http 服务,它并没有什么不同

    尽管有提供者方法表明您应该在客户端和服务器端都有一个数据提供者

    对于这个问题,我建议一个工厂,它公开你想要的方法并利用 $http 服务本身

    【讨论】:

      【解决方案6】:

      如果您要在多个控制器中使用该 REST API 调用,最好创建一个服务,该服务作为依赖项注入到需要它的控制器中。如前所述,您想使用 $resource 来处理 RESTful API。

      index.html:

      <!-- Include Angular and angular-resources -->
      <script src="angular.js"></script>
      <script src="angular-resource.js"></script>
      
      <!-- Set up your angular module -->
      <div ng-app="RESTfulServiceExample">
          <div ng-controller="HomeController">
              <ul>
                  <li ng-repeat="game in games">{{game.GameName}}</li>
              </ul>
          </div>
      </div>
      
      <script>
          // Inject angular-resource as ngResource into your module
          var gameListApp = angular.module('RESTfulServiceExample', ['ngResource']);
      
          // Create a service to call API which can be used by many controllers
          gameListApp.factory('GameService', ['$resource', function($resource) {
              return $resource('/game/:gameId', {gameId: '@id'});
          }]);
      
          // Create a controller that uses your service
          gameListApp.controller('HomeController', function($scope, GameService) {
              // GET: /game/
              var games = GameService.query();
      
              // Use response in HTML template
              $scope.games = games;
          });
      
          // Another controller could use the same service
          gameListApp.controller('GameController', function($scope, GameService) {
              // use GameService for another purpose
          });
      </script>
      

      参考:AngularJS: $resource

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-10-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-03-01
        • 2018-08-19
        相关资源
        最近更新 更多