在根级别显示加载指示器,直到所有路由解析完成

Show loading indicator at root level until all route resolves are complete

我已经在谷歌上搜索过这个问题,但找不到有效的解决方案。

我正在使用 AngularJS 1.5.5 和 .NET Web API 2 构建 Web 应用程序,我只想隐藏 ng-view 元素直到所有路线上的决议已完成。

我正在尝试使用 $routeChangeStart$routeChangeSuccess 在索引 html 中使用的 $rootScope 上设置一个变量来显示加载指示器并隐藏内容,直到变量为 false.

这是我的 routeChange 属性的路由代码:

_app.config([
        '$routeProvider', '$httpProvider', '$provide',
        function ($routeProvider, $httpProvider, $provide) {
                    $routeProvider.when('/Account',
                    {
                        templateUrl: '/Content/js/areas/account/account.html',
                        controller: 'accountController',
                        resolve: {
                            $accountResolver: function (accountService) {
                                return accountService.getMyAccountData();
                            }
                        },
                        caseInsensitiveMatch: true
                    });
            $routeProvider.otherwise({ redirectTo: '404' });

        }
]);

_app.run(['$rootScope', '$location', '$window', '$q', 'authService',
        function ($rootScope, $location, $window, $q, authService) {
            $rootScope.$on("$routeChangeStart",
                function (e, curr, prev) {
                    $rootScope.$loadingRoute = true;
                });
            $rootScope.$on("$routeChangeSuccess",
                function (evt, next) {
                    $rootScope.$loadingRoute = false;
                });
            $rootScope.$on("$routeChangeError",
                function (evt, next) {
                    $rootScope.$loadingRoute = false;
                });
        }]);

这是我的 html 使用 $loadingRoute 变量:

<body class="ng-cloak" data-ng-app="wishlist" data-ng-controller="appController">
    <wl-header></wl-header>
    <preloader ng-if="$loadingRoute"></preloader>
    <section ng-view ng-if="!$loadingRoute" class="container ng-cloak"></section>
</body>

我知道有很多文章对此进行了介绍,但 none 似乎对我有用。正如预期的那样,当路由更改开始时,$loadingRoute 被设置为 true,如果我将 {{$loadingRoute}} 添加到 <section></section> 标记之前的 HTML,我将看到这一点。然而,在解决 $accountResolver 之前,$routeChangeSuccess 被解雇,设置 $rootScope.$loadingRoute = false 这是意外的。

我的印象是 $routeChangeSuccess 只有在当前路线上的所有解析都完成后才会被解雇。

我在这里做错了什么吗?还是 Angular 只是改变了?

编辑:我还想补充一点,这种方法在以前的项目中有效,所以我真的不知道出了什么问题。我可以在每个页面控制器中手动设置$rootScope.$loadingRoute,但感觉太脏且无法维护。

编辑 2:

_app.factory('accountService', [
        'accountResource',
        function (accountResource) {
            var _self = this;

            return {
                register: function (authData) {
                    return accountResource.register(authData);
                },

                getMyAccountData: function () {
                    return accountResource.getMyAccountData();
                }
            }
        }
]);

_app.factory('accountResource', [
        '$resource', 'rootUrl',
        function ($resource, rootUrl) {
            var api = rootUrl() + 'api/Account';
            return $resource(api,
            {},
            {
                register: {
                    method: 'POST',
                    url: '{0}/register'.format(api)
                },
                getMyAccountData: {
                    method: 'GET',
                    url: '{0}/GetMyAccountData'.format(api)
                }
            });
        }
    ])

为了让解析器延迟路由更改,它应该 return 一个承诺。否则路由更改会立即发生,这就是在 accountService.getMyAccountData() 的承诺得到解决之前触发 $routeChangeSuccess 时发生的情况。

问题是 $resource 方法(因此 accountService.getMyAccountData())return 异步填充数据的自填充对象。此数据的承诺可用作 $promise 属性(请参阅 the reference),因此它应该用于解析器:

$accountResolver: function (accountService) {
  return accountService.getMyAccountData().$promise;
}

如果 accountService 应该是 accountResource 的纯粹基于 promise 的包装器,一种更简洁的方法是 return 来自其方法的 promise:

getMyAccountData: function () {
    return accountResource.getMyAccountData().$promise;
}