Дождитесь загрузки изображений на заводе angularjs

javascript angularjs image angularjs-ng-repeat angular-directive

625 просмотра

1 ответ

1848 Репутация автора

Я создал небольшую функцию, позволяющую пользователям искать названия фильмов. Это делает JSON-запросы от tmdb.org, который возвращает такие вещи, как заголовки, даты и постеры URL.

Контроллер:

    angular.module('movieSeat')
        .factory('moviesearchFactory', ['$http', '$q', '$rootScope', function ($http, $q, $rootScope) {

            var factory = {};

            function httpPromise(url) {
                var deferred = $q.defer();
                $http({
                    method: 'JSONP',
                    url: url
                })
                    .success(function (data) {
                        deferred.resolve(data.results);
                    })
                    .error(function () {
                        deferred.reject();
                    });
                return deferred.promise;
            }

            factory.getMovies = function (searchquery) {
                return httpPromise('http://api.themoviedb.org/3/' + 'search/movie?api_key=a8f7039633f2065942cd8a28d7cadad4' + '&query=' + encodeURIComponent(searchquery) + '&callback=JSON_CALLBACK')
            }

            return factory;

        }]);

Фабрика:

    angular.module('movieSeat')
        .controller('moviesearchCtrl', ['$scope', 'moviesearchFactory', function ($scope, moviesearchFactory) {

            $scope.createList = function (searchquery) {
                $scope.loading = true;
                moviesearchFactory.getMovies(searchquery)
                    .then(function (response) {
                        $scope.movies = response;
                    })
                    .finally(function () {
                        $scope.loading = false;
                    });

            }

        }]);

Шаблон:

    <div ng-controller="moviesearchCtrl" id="movieSearch">

        <div class="spinner" ng-show="loading">Loading</div>
        <input ng-model="searchquery" ng-change="createList(searchquery)" ng-model-options="{ debounce: 500 }" />
        {{ search }}

        <ul>
            <li ng-if="movie.poster_path" ng-repeat="movie in movies | orderBy:'-release_date'">
                <span class="title">{{ movie.title }}</span>
                <span class="release_date">{{ movie.release_date }}</span>
                <img ng-src="https://image.tmdb.org/t/p/w300_and_h450_bestv2/{{ movie.poster_path }}" class="poster"/>
            </li>
        </ul>
    </div>

Проблема с этой функцией заключается в том, что класс счетчика ожидает только запрошенные данные. Но простая загрузка JSON не занимает много времени, это загрузка изображений из API в браузере, что занимает некоторое время.

Это вызывает 2 вещи. Первый спиннер удаляется до того, как изображения отображаются в браузере, и поскольку все изображения загружаются асинхронно, это вызывает эффект водопада.

Самый простой способ решить эту проблему - отложить .thenвызов в контроллере до загрузки изображений для пользователя и затем перейти к .finallyвызову.

Но я не могу найти способ создать что-то подобное. Какие-нибудь советы?

Автор: Peter Boomsma Источник Размещён: 18.07.2016 12:55

Ответы (1)


1 плюс

34599 Репутация автора

Попробуйте это и дайте мне знать:

Идея состоит в том, чтобы использовать директиву для генерации завершенного события рендеринга:

dashboard.directive('onFinishRender', function ($timeout) {
    return {
        restrict: 'A',
        link: function (scope, element, attr) {
            if (scope.$last === true) {
                $timeout(function () {
                    scope.$emit(attr.onFinishRender);
                });
            }
        }
    }
});

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

    $scope.$on('dataLoaded', function(ngRepeatFinishedEvent) {
        // your code to check whether images has loaded
        var promises = [];
        var imageList = $('#my_tenants img');
        for(var i = 0; i < imageList.length; i++) {
            promises.push(imageList[i].on('load', function() {}););
        }
        $q.all(promises).then(function(){
            // all images finished loading now
            $scope.loading = false;
        });
    });

и в сторону HTML:

<div id = "my_tenants">
    <div ng-repeat="tenant in tenants" on-finish-render="dataLoaded">
        // more divs
    </div>
</div>
Автор: kukkuz Размещён: 18.07.2016 02:04
Вопросы из категории :
32x32