Angularjs 创建一个返回远程数据的角度过滤器?

Angularjs 创建一个返回远程数据的角度过滤器?,angularjs,filter,angularjs-filter,Angularjs,Filter,Angularjs Filter,我有一段我经常使用的代码,它调用API,以便根据发送给它的ID返回用户名 GetUserNames.get({users: user}, function (data) { $scope.userName = data[0]; }) 我想做的是把它变成一个过滤器,在那里我可以做类似的事情 {{userID | returnUserName}} 这样我就可以重用并保持我的控制器和视图干净。我写了这样的东西: angular.modu

我有一段我经常使用的代码,它调用API,以便根据发送给它的ID返回用户名

 GetUserNames.get({users: user}, function (data) {
                $scope.userName = data[0];
             })
我想做的是把它变成一个过滤器,在那里我可以做类似的事情

{{userID | returnUserName}} 
这样我就可以重用并保持我的控制器和视图干净。我写了这样的东西:

angular.module('app.filters').filter('returnUserName', function(GetUserNames) {
    return function(input) {
      GetUserNames.get({ users: input }, function (data) {
          console.log(data[0])
          return data[0]

      }); 
     }
});
当console.log返回正确的值时,我在页面上看不到它。我猜这是个时间问题。我能做些什么来实现这个功能,以便在页面上填充值

我有一段我经常使用的代码

每当你听到自己这样说时,想想服务而不是过滤器。虽然从理论上讲,您可以让筛选器进行远程调用,但这是对筛选器的严重滥用,可能会非常低效(可能会导致页面速度变慢,甚至可能会使用DDoS服务器)

您的模式应该更像

{{ returnUserName(userId) }}
或者甚至在某个地方预先输入用户名,然后就这样做

{{ userName }}
我有一段我经常使用的代码

每当你听到自己这样说时,想想服务而不是过滤器。虽然从理论上讲,您可以让筛选器进行远程调用,但这是对筛选器的严重滥用,可能会非常低效(可能会导致页面速度变慢,甚至可能会使用DDoS服务器)

您的模式应该更像

{{ returnUserName(userId) }}
或者甚至在某个地方预先输入用户名,然后就这样做

{{ userName }}

为了回答您的问题,这里有一段代码可以回答您的问题。 如果使用Angular 1.3.X,则可以使用$stateful,如:

angular.module('app.filters').filter('returnUserName', function($http) {
  var data = null, serviceInvoked = false;

  function realFilter(value) {
      return data;
  }

  filterStub.$stateful = true;
  function filterStub(value) {
    if( data === null ) {
        if( !serviceInvoked ) {
            serviceInvoked = true;
            $http.get('/url/test/').then(function (res) {
                data = res;
            });
        }
        return "";
    }
    else return realFilter(value);
  }
   return filterStub;
});
有关更多信息:


我希望它能帮助您。

为了回答您的问题,这里有一段代码可以回答您的问题。 如果使用Angular 1.3.X,则可以使用$stateful,如:

angular.module('app.filters').filter('returnUserName', function($http) {
  var data = null, serviceInvoked = false;

  function realFilter(value) {
      return data;
  }

  filterStub.$stateful = true;
  function filterStub(value) {
    if( data === null ) {
        if( !serviceInvoked ) {
            serviceInvoked = true;
            $http.get('/url/test/').then(function (res) {
                data = res;
            });
        }
        return "";
    }
    else return realFilter(value);
  }
   return filterStub;
});
有关更多信息:


我希望它能对您有所帮助。

正如@Florian Orpelier所提到的,您可以使用有状态过滤器,另外还可以使用一些缓存变量:

    angular.module("app").filter('svcData', function($http) {
        var cached = {};
        var apiUrl = 'http://my.service.com';
        function svcDataFilter(data_id, data_prop) {
            if (data_id) {
                if (data_id in cached) {
                    // avoid returning a promise!
                    return typeof cached[data_id].then !== 'function' ?
                        cached[data_id][data_prop] : undefined;
                } else {
                    cached[data_id] = $http({
                        method: 'GET',
                        url: apiUrl + data_id
                    }).success(function (data) {
                            cached[data_id] = data;
                        });
                }
            }
        }
        svcDataFilterFilter.$stateful = true;
        return svcDataFilterFilter;
})
然后像这样使用:
{{data\u id | svcData:'property'}}

注意:函数svcDataFilter将在每个摘要周期调用

此外,如果缓存变得太大,您需要找到一种重置缓存的方法

见:


还有plunker(上面的链接不会显示它,所以这里有一个直接链接):

正如@Florian或Elier所提到的,您可以使用一个有状态的过滤器,另外还可以使用一些缓存变量:

    angular.module("app").filter('svcData', function($http) {
        var cached = {};
        var apiUrl = 'http://my.service.com';
        function svcDataFilter(data_id, data_prop) {
            if (data_id) {
                if (data_id in cached) {
                    // avoid returning a promise!
                    return typeof cached[data_id].then !== 'function' ?
                        cached[data_id][data_prop] : undefined;
                } else {
                    cached[data_id] = $http({
                        method: 'GET',
                        url: apiUrl + data_id
                    }).success(function (data) {
                            cached[data_id] = data;
                        });
                }
            }
        }
        svcDataFilterFilter.$stateful = true;
        return svcDataFilterFilter;
})
然后像这样使用:
{{data\u id | svcData:'property'}}

注意:函数svcDataFilter将在每个摘要周期调用

此外,如果缓存变得太大,您需要找到一种重置缓存的方法

见:


还有plunker(上面的链接不会显示它,所以这里有一个直接链接):

有趣的问题,但我认为您需要的是一个指令,而不是一个过滤器。这不是过滤器的用途。它们主要用于格式化工厂代码,而不是过滤器。将cache设置为true,并在第一次调用后立即可用,无需为每个需要它的控制器发出请求。另外,您将返回回调中的哪个位置?无处您的外部函数没有返回任何有趣的问题,但我认为您需要的是一个指令,而不是一个过滤器。这不是过滤器的用途。它们主要用于格式化工厂代码,而不是过滤器。将cache设置为true,并在第一次调用后立即可用,无需为每个需要它的控制器发出请求。另外,您将返回回调中的哪个位置?无处您的外部函数不会返回任何结果,而顶部函数看起来非常干净——我以前从未以这种方式使用过服务。我可以从工厂中调用我的资源工厂(GetUserName)吗?@Ortal您可以在任何地方使用它,只需将它列为依赖项,上面的一个看起来非常干净——我以前从未以这种方式使用过服务。我可以从工厂调用我的资源工厂(GetUserName)吗?@Ortal您可以在任何地方使用它,只需将它列为依赖项即可