javascript - AngularJS : filter with AJAX

标签 javascript ajax angularjs asynchronous filter

我最近一直在从事 AngularJS 项目,在尝试创建一个使用通过 AJAX 请求加载的数据的过滤器时遇到了一个有趣的问题。

首先关于问题:

AngularJS 过滤器是一段同步代码(函数),它返回插入到 DOM 中的字符串。在大多数情况下,它工作得很好,例如以下过滤器首字母大写:

angular.module('myApp.filters', []).filter('capitilize', function() {
    return function (word) {
        return word.charAt(0).toUpperCase() + word.substr(1);
    }
});

这效果很好。现在的问题是,如果我不能立即返回想要的结果怎么办?假设我需要通过 AJAX 请求加载一些数据以获得所需的结果。如果我发出 AJAX 请求,我的 return 语句将在获取数据之前返回空结果。所以真正的问题是如何在加载数据时通知过滤器更新自身?

解决方案:

事实证明,解决方案就在我面前,但我花了一些时间才弄清楚魔法是如何发生的。假设我需要一个过滤器,根据艺术家的名字检索他们的传记(是的,一个有点疯狂的例子,但它证明了这一点):

angular.module('myApp.filters', []).filter('biography', function($q, $http) {
    var pending = {};

    return function (artist) {
        if ( !(artist in pending) ) {
            pending[artist] = null;
            $http.get('http://developer.echonest.com/api/v4/artist/biographies?api_key=FILDTEOIK2HBORODV&name='
                + artist + '&format=json&results=1&start=0&license=cc-by-sa')
                .then(function(response){
                    pending[artist] = response.data.response.biographies[0].text;
            });
        }

        return pending[artist] || '';
    }
});

它确实有效,但是如何呢?我发出了一个获取请求,得到了结果,但是它如何强制过滤器 self 更新。这里的关键是 Angular $q (受 Kris Kowal's Q. 启发的 promise /延迟实现)

来自 Angular 文档:

$q is integrated with the $rootScope.Scope Scope model observation mechanism in angular, which means faster propagation of resolution or rejection into your models and avoiding unnecessary browser repaints, which would result in flickering UI.

这意味着每当 promise 得到解决时,它都会导致更新,实际上这是来自 Angular 的代码:

  function done(status, response, headersString, statusText) {
    if (cache) {
      if (isSuccess(status)) {
        cache.put(url, [status, response, parseHeaders(headersString), statusText]);
      } else {
        // remove promise from the cache
        cache.remove(url);
      }
    }

    resolvePromise(response, status, headersString, statusText);
    if (!$rootScope.$$phase) $rootScope.$apply();
  }

希望这对您有帮助。这是示例,请记住该示例是进行跨域ajax调用,您需要禁用浏览器的跨域策略:

http://jsfiddle.net/pJuZ9/8/

重要提示:请记住不要使用相同的 ajax 请求淹没过滤器,否则您可能会得到以下结果:

Error: [$rootScope:infdig] 10 $digest() iterations reached. Aborting!
Watchers fired in the last 5 iterations: []

最佳答案

谢谢你的帖子,至少我知道我没有完全错。我有一个非常相似的场景:

1) 一个简单的翻译过滤器

module.filter('translate', ['Localization', function (localization) {
        var translateFilter = function (key) {
            return localization.get(key) || "[" + key + "]";
        };

        translateFilter.$stateful = true;

        return translateFilter;
    }]);

2) 存储 JS 字典的本地化服务。这是通过 XHR 更新的。这意味着字典有多种可能的状态:

  • 初始化之前没有本地化 => 空
  • 初始化后的默认本地化 => 非空
  • 加载默认值后用户定义的本地化 => 非空

我的问题是,即使执行了摘要,过滤器结果在 XHR 调用结束后也没有更新(重新渲染)。我必须添加

translateFilter.$stateful = true;

使其发挥作用。即使将过滤器依赖项从 service 更改为 value 也没有帮助。有人可能会觉得这很有帮助,或者更好,告诉我,我做错了什么:-)

关于javascript - AngularJS : filter with AJAX,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24586315/

相关文章:

javascript - Rails 从远程获取事件触发器 :true

angularjs - WebSharper 与 Angular

angularjs - Angular 模块组织/架构

android - 在 Cordova App 中调试崩溃

javascript - 是删除对函数的引用,还是删除函数的实例?

javascript - Json响应vue

javascript - 如何解释 Firebug Net 面板中的灰色项?

php - 这种基于浏览器的乒乓球游戏可以使用什么技术?

javascript - 如何在 setTimeout 后返回 jsx

ajax - 在 MVVM/Knockoutjs Web App 中保存更改的最佳方法?