Tulun
Tulun

Reputation: 469

$scope variable from api call sometimes doesn't update

So I am trying to display some data after a user successfully logs into an external API.

When I login, sometimes the data doesn't update properly until I refresh the page; In addition, this bug seems to only persist after a full refresh AND I have logged out of the API.

the service is like this:

angular.module('myApp')
  .service('PlayerAPICall', function ($http, $q) {
    // AngularJS will instantiate a singleton by calling "new" on this function
    var deferred = $q.defer();

    return {
      getPlayerInfo: function() {
        var getPlayerBasic = {
          method: 'GET',
          url: 'API_URL',
          headers: {
            'Accept': 'HEADER'
          } 
        };

        // This API call returns some basic player information for the current logged in user.
        $http(getPlayerBasic).success(function(response) {
          deferred.resolve(response);
        });

        return deferred.promise;
      },
    }
  });

My directive for this is like this (With the pertinent information)

angular.module('myApp')
  .controller('NavbarCtrl', function($scope, PlayerAPICall) {

    // Declare $scope objects.
    $scope.playerBasic;

    PlayerAPICall.getPlayerInfo().then(function(response) {
      $scope.playerBasic = response;
    });

  })

The partial looks like this:

  <div class='links-container'>
    <div class='row'>
      <div class='inputs'>
        <form ng-submit='submit()'>
        <p ng-show='playerBasic.first_name != null' class='md-text logout-container'>
          Hello, {{playerBasic.first_name}}
          <span class='logout-span'><button class='btn btn-primary logout-btn' type='submit' ng-model='submit'>Logout</button></span></p>
        <p ng-show='playerBasic.first_name == null' class='md-text logout-container'>
          Hello, {{playerBasic.email}}
          <span class='logout-span'><button class='btn btn-primary logout-btn' type='submit' ng-model='submit'>Logout</button></span>
        </p>
        </form>
      </div>
    </div>

Although I KNOW the name variable exists for this user, it sometimes says:

'Hello, ' Instead of 'Hello, name'.

I'm not entirely sure why the $scope doesn't change.

Upvotes: 0

Views: 75

Answers (2)

tommybananas
tommybananas

Reputation: 5736

You have to move the creation of deferred into the function call because you can't reuse a defer object.

return {
  getPlayerInfo: function() {
    var getPlayerBasic = {
      method: 'GET',
      url: 'API_URL',
      headers: {
        'Accept': 'HEADER'
      } 
    };

    var promise = $http(getPlayerBasic);
    var derivedPromise = promise.then(function(response) {
        return response.data;
    }); 
    return derivedPromise;
  },
}

You also don't even need to create a new promise because $http returns a promise itself, so your implementation is redundant. You can just do: return $http(getPlayerBasic);

Upvotes: 3

georgeawg
georgeawg

Reputation: 48968

There is no need to manufacture a promise with $q.defer() as the $http service already returns a promise:

angular.module('myApp')
  .service('PlayerAPICall', function ($http, $q) {
    //var deferred = $q.defer();

    return {
      getPlayerInfo: function() {
        var getPlayerBasic = {
          method: 'GET',
          url: 'API_URL',
          headers: {
            'Accept': 'HEADER'
          } 
        };

        //$http(getPlayerBasic).success(function(response) {
        //  deferred.resolve(response);
        //});
        //return deferred.promise;

        var promise = $http(getPlayerBasic);
        var derivedPromise = promise.then(function(response) {
            //return data to chain
            return response.data;
        }); 
        return derivedPromise;
      },
    }

});

The above example creates a promise that resolves with the data property of the response object if successful. Errors are rejected with the response object of the erroneous response.

The advantage of deriving promises this way is that the promise chain is not broken if there is an error. Failure to provide a rejection to $q.defer() will cause the $q.defer promise to hang when there are errors and will create memory leaks.

Upvotes: 1

Related Questions