【问题标题】:Inside my own Angular service, how do you get the return value back to the Controller that called the service?在我自己的 Angular 服务中,如何将返回值返回给调用该服务的控制器?
【发布时间】:2023-03-11 06:08:01
【问题描述】:

我无法确定 $http 中角度的成功和错误回调以及 Promise 的“then”部分。 $http 服务返回一个承诺。 “成功”回调是“那么”的一个例子吗? 如果我将 $http 放在自己的服务中怎么办?我该怎么做?

我认为代码更容易显示我的问题:

app.controller('MainCtrl', function ($scope, $log, BooksService) {
    BooksService.retrieveAllBooks().then(function(results) {
      $scope.allBooks = results;
    });
  });


app.factory('BooksService', function($http,$log) {
  var service = {
    retrieveAllBooks: function() {
      return $http({
        method: 'GET','https://hugebookstore.org/allbooks'
        headers: {
            "Content-Type": "application/json",
            "Accept": "application/json"
        }
      }).success(function(data, status, headers, config) {
         var allbooks = transformDataIntoBooksArray(data);//this function exists and just takes raw data and turns them into Book objects
         return allbooks;/*how is this "success" callback related to the "then"() callback in app.controller above?*/
      };
      }).error(function(data, status, headers, config) {
        $log.error('here is an error'+data + status + headers + config);
      });
    }
  };
  return service;
});

关于app.controller代码的问题:

我需要在app.controller? 中使用"then()" 函数吗

我只想让我的控制器使用BooksService 为我获取所有书籍的列表。 BooksService 已经有一个“then”类型的子句,即“success”回调。好像我有一个不必要的“then”。真的吗?

另外,什么时候调用“then”,我可以在then's回调函数的参数中添加任何内容吗?

我不明白默认提供了哪些参数以及我可以添加什么。

关于app.factory代码的问题:

首先,这就是我理解的代码要做的事情。

我正在使用 factory() 方法而不是 Angular 中可用的 service() 方法创建一个 BooksService。 我正在定义一个名为retrieveAllBooks() 的函数,它在后台使用$http 在Angular 中发出异步GET 请求,它本身就是一项服务。 RetrieveAllBooks() 只不过是 $http GET 服务的一个包装器,它使客户可以轻松地调用 BooksService.retrieveAllBooks() 并获得一系列 Book 对象。

success”回调何时执行,它与我的app.controller? 中的“then”回调有什么关系

我的success() 回调中的return 值似乎不会返回到app.controller。为什么?

我怎样才能将 allbooks 数组返回到 app.controller,它最初称为 BooksService.retrieveAllBooks()

success 回调中是否允许使用其他参数?

我需要从retrieveAllBooks() 函数定义中返回什么?我是单独返回 $http promise,还是需要同时从成功和 error 回调中返回 return

我知道这是冗长的,但我希望有人可以帮助我,b/c 这是模式——将我的网络调用分离到它自己的service 层,而不是直接在我的@987654351 中调用 $http @层,将一遍又一遍地完成。

谢谢!!

【问题讨论】:

    标签: javascript angularjs http service promise


    【解决方案1】:

    successerror 处理程序特定于 $http 返回的承诺。但是,它们类似于.then(function onFulfill(){}, function onReject(){})

    如果您想直接返回该承诺或实现其他内容,这取决于您。

    通常,您的控制器不应该关心您的服务如何处理请求。因此,在我看来,您不应该直接返回该承诺。只需处理服务中的成功和错误情况。如果请求成功则返回结果,如果请求失败则抛出错误。

    然后,您可以在控制器中使用通用 .then(function onFulfill(){}, function onReject(){}) 模式,因为这始终是有效的,并且是 Angular 中的承诺所期望的。

    onFulfill 回调始终接收您的结果作为参数,onReject 回调接收错误作为参数。

    那么,你有什么选择?要么将 .success.error 回调完全放在你的服务中,然后在你的控制器中处理成功案例中的转换,或者创建一个新的延迟承诺来返回转换后的结果:

    app.factory('BooksService', function($http,$log,$q) {
      var service = {
        retrieveAllBooks: function() {
          var deferred = $q.defer();
          $http({
            method: 'GET','https://hugebookstore.org/allbooks'
            headers: {
                "Content-Type": "application/json",
                "Accept": "application/json"
            }
          }).success(function(data, status, headers, config) {
             var allbooks = transformDataIntoBooksArray(data);//this function exists and just takes raw data and turns them into Book objects
             deferred.resolve( allbooks );
          };
          }).error(function(data, status, headers, config) {
            $log.error('here is an error'+data + status + headers + config);
            deferred.reject( new Error( 'here is an error'+data + status + headers + config );
          });
          return deferred.promise;
        }
      };
      return service;
    });
    

    不过,如果我们考虑: - Angular 已经跟踪错误 - 延期是多余的,可以避免 - Content-Type 和 Accept 无论如何都是由 Angular 和 serer 生成的。 - 我们可以为我们的操作保存匿名包装器

    所以,我们最终得到:

    app.factory('BooksService', function($http) {
      return {
        retrieveAllBooks: function() { 
          return $http.get('https://hugebookstore.org/allbooks').
                 then(transformDataIntoBooksArray); // Error tracked by Angular already
          }
        }
    });
    

    【讨论】:

    • 嗨,奥利弗,非常感谢。我绝对同意控制器不应该做任何转换,应该交给 Books 数组。看起来我会接受你的实现,我需要阅读 $q 和 defer() 方法。出于某种原因,我认为 $q 在最新版本的 angular 中不再需要(哎呀!),或者肯定是高级用法,我的“通常用例”不需要,因此对其进行了掩饰。
    • “成功和错误处理程序...只是实现 .then(...) 的语法糖”。抱歉,这不是真的。.success().error() 都保证返回其原始输入承诺,而.then() 保证返回一个新承诺,其值/原因由其处理程序中的任何一个确定(如果有)被执行。 .then() 因此具有.success().error() 单独不具备的“过滤”能力。 Angular 文档并不擅长提出这一点。
    • 除了@Roamer-1888 所说的,您不需要延迟返回。 $http 返回一个承诺。如果您使用.then,您可以简单地返回结果承诺并使用返回值。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-08-19
    • 1970-01-01
    • 2015-12-02
    • 2016-09-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多