AngularJS:如何在过滤器中使用$ http

时间:2013-11-08 16:47:01

标签: angularjs

我想在过滤器中向后端发出请求并返回我的请求结果。 问题是服务$ http返回一个承诺,这就是问题。

目前这个问题我使用$ timeout和我小提琴中的角度承诺: my fiddle

在我的过滤器中,我使用$ timeout和promise,但最终目标是使用请求http:

myApp.filter('filterHello', function ($http,$timeout,$q) {
return function (company_id) {
    console.log("in the filter");
    var deferred = $q.defer();   
    $timeout(function() {
        deferred.resolve("ca marche");
    }, 2000);                  
    return deferred.promise;
};

});

然后在我的视图中,我使用我的过滤器,假设显示“ca marche”,延迟2秒,但这不起作用:

<div ng-controller="MyCtrl">
   {{hello|filterHello}}
</div>

你可以看到过滤器什么也没有返回,而且我认为过滤器中存在无限循环。

如果您不明白我为什么要在过滤器中使用请求http,答案很简单。 例如,我有一个对象用户,其字段为:email,name,company_id .. 我还有一个其他对象公司的字段:name,createOn,... 我想使用这样的过滤器来显示用户公司的名称:

{{user.company_id | ShowNameCompany}}

所以,我需要在过滤器中向我后端的公司控制器请求http。

我希望有人可以帮助我。

2 个答案:

答案 0 :(得分:16)

我认为你不应该这样使用过滤器。过滤器用于根据可选参数转换输入。

这里的问题是你立即从过滤器函数返回一个promise。而这也不是Angular可以通过过滤器处理的结果。

我的建议是这样的 - 首先获取结果,根据结果使用过滤器:

var app = angular.module("my.module");

app.controller("MyCtrl", ['$http', '$scope', function(http, scope) {
  scope.hello = "foo";
  http.get('http://my.service.com').then(function(data) {
    scope.filterParams = data;
  }, function(err) {
    scope.filterParams = undefined;
  });
}]);

app.filter("filterHello", function() {
  return function(input, params) {
    if(typeof params === "undefined") {
      return "";
    }
    //work with the params here
  };
});

并在模板中:

<div ng-controller="MyCtrl">
  {{hello|filterHello:filterParams}}
</div>

编辑:请阅读您的解释。对我来说,这将成为指令的候选人:

app.directive("companyName", ['$http', function(http) {
  return {
    template: "<span>{{name}}</span>",
    scope: {
      companyId: "="
    },
    link: function(scope) {
      http.get("http://my.service.com/companies/" + scope.id).then(function(result) {
        scope.name = result.name;
      }, function(err) {
        scope.name = "unknown";
      });
    }
  }
}]);

并在模板中:

<span company-name company-id="user.company_id"></span>

如果你有很多公司,你应该预先加载这些名字(也许最初会发送第一个回复吗?),因为你要根据请求轰炸你的服务器。

答案 1 :(得分:1)

或者您可以使用有状态过滤器:

    angular.module("app").filter('companyName', function($http) {
        var cached = {};
        var apiUrl = 'http://my.service.com';
        function companyNameFilter(company_id) {
            if (company_id) {
                if (company_id in cached) {
                    // avoid returning a promise!
                    return typeof cached[company_id].then !== 'function' ?
                        cached[company_id] : undefined;
                } else {
                    cached[company_id] = $http({
                        method: 'GET',
                        url: apiUrl + company_id
                    }).success(function (companyName) {
                            cached[company_id] = companyName;
                        });
                }
            }
        }
        companyNameFilter.$stateful = true;
        return companyNameFilter;
})

并像这样使用它:{{company_id | companyName}}

注意:函数companyNameFilter将在每个摘要周期上调用。

此外,如果缓存增长过大,您需要找到一种方法来重置缓存。

请参阅:https://glebbahmutov.com/blog/async-angular-filter/

和plunker(上面的链接不会显示它,所以这里是直接链接):http://plnkr.co/edit/EK2TYI1NZevojOFDpaOG?p=preview