2013-12-06 5 views
3

При использовании AngularJS я постоянно сталкиваюсь с проблемой того, как работать с асинхронными функциями и функциями обратного вызова. В нижеследующем, как я могу изменить PostsService.getPostBySlug, чтобы вернуть нужный пост?Фильтрация данных из функции обратного вызова

сообщений службы

Website.factory('PostsService', 
[ '$filter', '$http', function(filter, $http) 
{ 
    // declare service 
    var PostsService = {}; 

Возврат всех сообщений (читает posts.json)

PostsService.getPosts = function(callback) 
    { 
     $http 
      .get('posts/posts.json') 
      .success(callback); 
    } 

Возврат один пост на основе его слизня

PostsService.getPostBySlug = function(slug, callback) 
    { 
     // declare post 
     var postForSlug = null; 
     console.log(postForSlug); // prints 'null' 

     // get all posts from service 
     var posts = PostsService.getPosts(function(data) 
     { 
      // all posts 
      var posts = data; 
      console.log(posts); // prints array of objects 

      // return all posts 
      return posts; 
     }); 

     // filter by slug 
     postForSlug = filter('filter') 
     ( 
      posts, 
      { 
       'slug': slug 
      } 
     ); 

     console.log(postForSlug); // prints 'undefined' 

     // return post for the given slug 
     return postForSlug; 
    } 

Возвращение службы

// return service 
    return PostsService; 

}]);  

Выход

null BlogController.js:26 
undefined BlogController.js:51 
[Object, Object] BlogController.js:33 

, который идет, чтобы показать, что порядок исполнения отличается от того, что я ожидал. Я знаю, что речь идет о асинхронном поведении и функции обратного вызова, но я действительно не знаю, как это исправить. Я продолжаю сталкиваться с этой проблемой, и было бы очень признательно, если бы кто-нибудь мог показать мне, как бороться с этим типом ситуации.

+1

Я бы предложил читать о обещаниях в [$ HTTP] (http://docs.angularjs.org/api/ng.$http) и $ кв. – calebboyd

ответ

1

В то же время, вот что я хотел бы сделать.

WebSite.controller('BlogController',function(PostsService,$scope){ 
    PostService.getPosts() 
     .then(function(posts){ 
      $scope.posts = posts; 
     }); 
    PostService.getPostBySlug() 
     .then(function(post){ 
      $scope.postBySlug = post; 
     }); 

}); 

И ваш PostsService будет выглядеть следующим образом: (а прикованный обещание!)

PostsService.getPosts = function() 
{ 
    return $http.get('posts/posts.json').then(function(response){ 
     var data = response.data; 
     //look it over, is it what you want? 
     return data; 
    },function(errResponse){ 
     //handle error. 
    }); 
} 

Что касается фильтра. Они применяются в представлении с помощью оператора | с желаемыми параметрами в представлении, они не очень полезны вне шаблона.

Так Ваш getPostsBySlug должен выглядеть следующим образом:

PostsService.getPostBySlug = function(slug) 
{  
    return this.getPosts().then(function(posts){ 
     var post = {}; 
     angular.forEach(posts,function(value,index){ 
      if(value.slug == slug){ 
       post = value; 
      }    
     }); 
     return post; 
    }); 
} 

Надеется, что это помогает!

+0

Да, у меня есть контроллер, который в значительной степени делает то, что делает ваш. Но это был не вопрос. Мой вопрос состоял в том, как очистить беспорядок, который я сделал в 'PostsService.getPostBySlug', чтобы он фактически возвращал одно сообщение (контроллеру, который его называет)? – Ben

+0

Я хочу, чтобы фильтрация выполнялась в сервисе. Вы бы не получили все сообщения из db, а затем отфильтровали их до одного в своем представлении, используя '|', не так ли? Тот же случай для этой реализации, который использует json-файл вместо db. – Ben

+0

Файл json содержит несколько сообщений.Каждое сообщение имеет свойство «slug». 'PostsService.getPostBySlug' вызывается из контроллера и должен возвращать одно сообщение на основе его пули. Сообщение slug - это уникальный идентификатор, похожий на id. Надеюсь, что это станет более ясным. – Ben

1

Я бы использовал обещания и обещание $ q Api для достижения этого.

см http://jsfiddle.net/6WuM3/

module.factory('PostsService', ['$filter', '$http', '$q', function (filter, $http, $q) { 
    // declare service 
    var PostsService = {}; 
    PostsService.getPosts = function() { 
     var defered = $q.defer(); 
     $http.get('posts/posts.json').then(function(response){ 
      defered.resolve(response.data); 
     }); 
     return defered.promise; 
    } 
    PostsService.getPostBySlug = function (slug) { 
     var defered = $q.defer(); 
     PostsService.getPosts().then(function(posts){ 
      var filtered = filter('filter')(posts, { 
       'slug': slug 
      }); 
      defered.resolve(filtered); 
     }); 
     return defered.promise; 
    } 
    return PostsService; 
}]) 

привет :)

+0

Я пробовал свой выше код в сочетании с 'Website.controller (« PostsCtrl » », ['$ scope', 'PostsService', function ($ scope, PostService) {$ scope.posts = PostService.ge tPosts(); }]); '(как в вашем jsfiddle). Сообщения не отображаются в представлении, и я думаю, что проблема 'PostService.getPosts()' не возвращает фактические объекты post, а вместо этого возвращает объект Object {then: function, catch: function, finally: function} '. – Ben

+0

Изменение кода контроллера из '$ scope.posts = PostService.getPosts();' 'к PostsService.getPosts(), а затем (функция (ответ) \t { \t \t $ scope.posts = ответ; }). 'решает проблему. Но я действительно не понимаю, почему? – Ben

Смежные вопросы