【问题标题】:Angular 1 promise in serviceAngular 1 承诺服务
【发布时间】:2017-03-01 09:25:49
【问题描述】:

我一直在疯狂地试图让某些东西在 Angular 1.3 中工作,这甚至可能是不可能的......但看起来应该是这样。基本上,我想编写一个只返回计算值而不是承诺的服务。

我有一个服务,它发出一个 $http.get 请求并返回一个承诺。我想从另一个服务中调用它,获取该数据,对其进行操作并返回一个值。我不想处理 .then 一旦我打电话给我的服务。我的理由是我想要一个可共享的函数,我可以调用它并接收一个实际值,这样我就可以将它用作诸如 ng-show 之类的条件。就像我说的那样,我会在控制器中编写这个函数并使用 .then 用来自 promise 的数据分配一个变量,但我不想在我需要它的每个控制器中都写这个。

例子:

app.factory('searchService', ['$http', function($http) {
  return {
    performSearch: function(searchString) {
      return $http.get('http://asdf.com/search/' + searchString);
    },
    getItemCount: function(itemName) {
      var _this = this;
      this.count = 0;

      this.performSearch(itemName).then(
        function successCallback(resp) {
          _this.count = resp.data.items.length;
        },
        function errorCallback() {
          // This section doesn't matter right now
        };

       return this.count;
    }
  };
}]);

所以我希望能够从控制器调用它并返回“5”或其他东西。或者更好的是,从像“ng-show="blahCtrl.getItemCount('item_search_string') == 0”这样的 ng-show 调用它。同样,我有多个控制器,我可能需要它,所以我不想重复到处都是函数,只是为了提取我需要的数字。

但这对我不起作用...我的返回值始终是我最初设置 this.count 的值。我在几个地方插入了一个console.log,并且已经看到(似乎) this.count 在回调函数可以设置其值之前返回。无论我做什么,我都无法从这项服务中返回一个单一的值,这让我发疯了!更让我困惑的是,如果我要从控制器内部执行此代码:

var _this = this;
searchService.performSearch('asdf').then(
  function(data) { _this.searchResults.data; }
);

它工作得很好,我在 searchResults 变量中得到我的承诺数据没问题。由于某种原因,它在服务内部无法以这种方式工作。

希望这是有道理的,我可能有点啰嗦或不清楚。任何帮助都将不胜感激......我已经花了尽可能多的时间研究这个并尽可能自己使用试验和错误。

谢谢!

【问题讨论】:

  • 看看 $object 使用 Restangular 非常接近你的愿望......
  • 从您的要求来看,您似乎打算将 performSearch 作为私有函数,所以为什么要返回它。而是返回 {getItemCount: function(){....}}。在返回 {} 之前编写函数 performSearch (){}。当您以这种方式定义它而不返回它时,这是一个私有函数。如果您想要调用 performSearch,那么必须使用 .then 仅在语义上才有意义 - “调用 performSearch 并在结果时执行 THEN --DO-- 某事。似乎您陷入了您想要的、代码质量和语法之间。跨度>

标签: javascript angularjs angularjs-service angular-promise


【解决方案1】:

我看到的一个解决方案。

把这个放在控制器中

app.controller('ctrl', function ($scope, searchService) {
   $scope.searchService = searchService;
   searchService.getItemCount();
});

进入所有视野

{{ searchService.count }}

我认为,对每个ng-if、ng-show 等都提出请求是不好的。

【讨论】:

    【解决方案2】:

    您将需要使用 $q (https://docs.angularjs.org/api/ng/service/$q)。您的功能在承诺完成之前返回。您的 getItemCount 应如下所示:

    app.factory('searchService', ['$http', '$q', function($http, $q) {
      return {
        performSearch: function(searchString) {
          return $http.get('http://asdf.com/search/' + searchString);
        },
        getItemCount: function(itemName) {
          var deferred = $q.defer();
    
          this.performSearch(itemName).then(
            function successCallback(resp) {
              deferred.resolve(resp.data.items.length);
            },
            function errorCallback(err) {
              deferred.reject(err);
            };
    
           return deferred.promise;
        }
      };
    }]);
    

    【讨论】:

    • 这仍然返回一个承诺,对吧?当我尝试这个时,我得到的只是 {} 返回。当我只是延迟返回时,我看到它是 {"promise":{}}
    • 这将返回一个将被解析为resp.data.items.length 的承诺。如果您想控制台记录项目的数量,您应该将该语句放在 .then 函数中。例如:getItemCount('myitem').then(function(response) { console.log(response) } );
    • 是的,我已经做到了。但这里的重点是在我运行这个服务函数时只返回一个整数,而不是我必须再次处理的另一个承诺。有没有办法做到这一点?我的意思是,如果我在 performSearch() 函数中添加 .then() 并在那里解决承诺,那么当我在 getItemCount 中时,我不应该只能说 performSearch().then() 并分配数据从已解决的承诺到我可以返回的变量?但它永远不会那样工作......它总是跳过我的 performSearch().then 并在不等待的情况下返回。
    • 你知道,ng-show 接受一个承诺作为一个值,所以你可以做"ng-show=myCtrl.getItemCount('myitem')>0"。避免承诺的唯一方法是在调用 performSearch.then() 的控制器中设置它,或者将此工厂转换为服务并在 performSearch 方法中设置 this.count 属性。
    猜你喜欢
    • 2015-08-12
    • 1970-01-01
    • 2013-12-19
    • 2017-02-21
    • 1970-01-01
    • 1970-01-01
    • 2013-06-29
    • 2015-12-02
    • 2017-09-13
    相关资源
    最近更新 更多