简体   繁体   中英

Resolve 2 arrays before anything on the page with a promise

I have 2 arrays, sports and leagues and I want those arrays to become resolve before anything on the page, I will paste all of my code regarding those arrays I just mentioned. I need to do this due to an issue I am having with the Angular filters.

this is my html

<div ng-repeat="sport in sportsFilter = (sports | filter:query)">
  <div ng-if="sport.leagues.length">
     <!--first array-->
     {{sport.name}}
  </div>
      <div ng-repeat="league in sport.leagues">
        <!--second array-->
        {{league.name}}
      </div>
    </div>

controller

  .controller('SportsController', function($scope, $state, AuthFactory,   
               SportsFactory, Sports) {

    $scope.sports = [];
    $scope.sportPromise = Sports;


    AuthFactory.getCustomer().then(function(customer) {
      $scope.customer = customer;
      SportsFactory.getSportsWithLeagues(customer).then(function(sports) {
        $ionicLoading.hide();
        if (sports.length) {

          $scope.sportPromise = Sports;

          $scope.sports = sports;

        }else {
          AuthFactory.logout();
        }
      }, function(err) {
        console.log(err);
      });
     }
    });

    $scope.isSportShown = function(sport) {
      return $scope.shownSport === sport;
    };

  });

and here de app.js so far, I thought with this I was resolving the arrays, actually the must important is the array named leagues , but still is giving me troubles

.state('app.sports', {
  url:'/sports',
  views:{
    menuContent:{
      templateUrl:'templates/sportsList.html',
      controller:'SportsController',
      resolve: {
        Sports: function(SportsFactory, AuthFactory, $q) {
          var defer = $q.defer();

          AuthFactory.getCustomer().then(function(customer) {
            SportsFactory.getSportsWithLeagues(customer).then(function(sports) {

              var sportLeagues = _.pluck(sports, 'leagues'),
                  leaguesProperties = _.chain(sportLeagues).flatten().pluck('name').value();

              console.log(leaguesProperties);

              defer.resolve(leaguesProperties);

            });

          });
          return defer.promise;
        }
      }
    }
  }
})

UPDATE:

the page is loading and I my filter is getting the array leagues empty, so is not searching thru to it, so I need that array to load first than the filters.

Here's how this could work at a high-level, including avoiding some mistakes you are making.

Mistakes:

  • You don't need to use $q.defer when the API you are using is already returning a promise. Just return that promise. What you are doing is called an deferred anti-pattern .
  • resolve is used when you need to do something (like authentication) before you are hitting a particular state. You are under-using the resolve by not resolving the customer , and instead doing this in the controller.
  • resolve property of $stateProvider can accept other resolves as parameters.

With these out of the way, here's how it could work:

.state('app.sports', {
  resolve: {
    customer: function(AuthFactory){
       return AuthFactory.getCustomer();
    },
    sports: function(SportsFactory, customer){
       return SportsFactory.getSportsWithLeagues(customer);
    },
    leagues: function(sports){
       var leagueProperties;

       // obtain leagueProperties from sports - whatever you do there.

       return leagueProperties;
    }
  }
});

Then, in the controller you no longer need AuthFactory - you already have customer :

.controller('SportsController', function($scope, customer, sports, leagues){
   $scope.sports = sports;
})

As per request in the comments of New Dev's answer the same only using array notation so that the code remains minifiable:

.state('app.sports', {
    resolve: {
        customer: ['AuthFactory', function(AuthFactory){
            return AuthFactory.getCustomer();
        }],
        sports: ['SportsFactory', 'customer', function(SportsFactory, customer){
            return SportsFactory.getSportsWithLeagues(customer);
        }],
        leagues: ['sports', function(sports){
            var leagueProperties;

            // obtain leagueProperties from sports - whatever you do there.

            return leagueProperties;
        }]
    }
});

A little explanation to go with that, when you minify this:

function (AuthFactory) {
    return AuthFactory.getCustomer();
}

You get something like this:

function (_1) {
    return _1.getCustomer();
}

Now it will try to inject _1 which is not defined so the code will fail. Now when you minify this:

['AuthFactory', function(AuthFactory){
    return AuthFactory.getCustomer();
}]

You'll get this:

['AuthFactory', function(_1){
    return _1.getCustomer();
}]

And that will keep working because now _1 is assigned to AuthFactory because angular injects the first parameter in the function with the first string in the array.

Reference: https://docs.angularjs.org/guide/di (see: inline array notation)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM