Почему мое представление AngularJS не обновляется после вызова AJAX с помощью Parse.com JavaScript SDK?


Вот мой взгляд

<div ng-repeat="blog in blogs">
<h3>{{blog.title}}</h3>
<h4>{{blog.post}}</h4>
</div>

Мой Код Контроллера:

   demoApp.controller('myController', ['$scope', 'blogService', function ($scope,   
    blogService)
    {
        $scope.blogs = blogService.getBlogs();
    }]);

Мой код на службе. Это включает в себя асинхронный вызов Parse.com JavaScript sdk.

this.getBlogs = function () 
{        
   var BlogPost = Parse.Object.extend("BlogPost");
   var blogPost = new BlogPost();
   var blogs  = [];
    var query = new Parse.Query(BlogPost);
    query.find({
        success: function(results) {
            console.log(results[0].get("title"));
            for (var i = 0; i < results.length; i++)
            {
                blogs.push(
                    {
                        title : results[i].get("title"),
                        post : results[i].get("post")
                    });
            }
            console.log(blogs);
        },
        error: function(error) {
            alert("Error: " + error.code + " " + error.message);
        }
    });
    return blogs;
}; });

Журнал консоли console.log(blogs); отлично показывает возвращенные данные. Просто представление не обновляется после извлечения этого значения.

3 2

3 ответа:

Код в обратных вызовах выполняется "вне мира Angular", что означает, что цикл $digest не будет запущен и изменения не будут отражены в DOM.

Вам нужно использовать $apply :

$apply () используется для выполнения выражения в angular извне угловой каркас. (Например, из событий DOM браузера, библиотеки setTimeout, XHR или сторонних производителей). Потому что мы взываем к угловой каркас нам нужен для выполнения правильного объема жизни цикл из обработка исключений, выполнение вахт.

Введите $rootScope в вашу службу и, например:

success: function(results) {
  $rootScope.$apply(function () { 
    console.log(results[0].get("title"));
    for (var i = 0; i < results.length; i++)
    {
        blogs.push(
            {
                title : results[i].get("title"),
                post : results[i].get("post")
            });
    }
    console.log(blogs);
  });
},

Ваш обратный вызов "success" выполняется асинхронно, и angular не знает, когда это произойдет. Чтобы сообщить angular об успешном обратном вызове, вы можете обернуть его в $ scope.$apply

success: function(results) {
    $scope.$apply(function() {
        console.log(results[0].get("title"));
        for (var i = 0; i < results.length; i++)
        {
            blogs.push(
                {
                    title : results[i].get("title"),
                    post : results[i].get("post")
                });
        }
        console.log(blogs);
    });
}

Обещайте, что ваши услуги вернутся!

.factory('factoryReturningPromise', function (){
   ...
  return query.find()

  .then(function(results){
     ...
    // make sure the return value is a resolved promise
    return Parse.Promise.as(blog);
  },

  function(error){

    // we are here because of query error - return rejected promise
    return Parse.Promise.error(error);
  });
})

Тогда вам нужно только обернуть его в локальный $scope.$apply внутри вашего контроллера:

.controller('myController', function ($scope, factoryReturningPromise) {
   $scope.$apply(function(){

      blogService.getBlogs()

      .then(function(blogs){

        $scope.blogs = blogs;
      }, function (error) {

        ... and deal with errors ... show bad news to user etc
      });
   });
})

Таким образом, будут проверены только локальные циклы дайджеста со всеми часами.