来自api调用的$ scope变量有时不会更新

时间:2022-03-13 00:07:25

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

所以我试图在用户成功登录外部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.

当我登录时,有时数据在我刷新页面之前不能正确更新;此外,这个错误似乎只在完全刷新后才会持续存在并且我已经注销了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.

我不完全确定为什么$ scope不会改变。

2 个解决方案

#1


1  

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

由于$ http服务已经返回一个承诺,因此无需使用$ q.defer()制作承诺:

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.

上面的示例创建一个promise,如果成功,则使用响应对象的data属性解析。使用错误响应的响应对象拒绝错误。

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.

以这种方式推导promises的好处是,如果出现错误,promise链不会被破坏。如果没有提供拒绝$ q.defer()将导致$ q.defer承诺在出现错误时挂起,并会造成内存泄漏。

#2


3  

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);

您甚至不需要创建新的承诺,因为$ http会返回一个承诺本身,因此您的实现是多余的。你可以这样做:return $ http(getPlayerBasic);

#1


1  

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

由于$ http服务已经返回一个承诺,因此无需使用$ q.defer()制作承诺:

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.

上面的示例创建一个promise,如果成功,则使用响应对象的data属性解析。使用错误响应的响应对象拒绝错误。

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.

以这种方式推导promises的好处是,如果出现错误,promise链不会被破坏。如果没有提供拒绝$ q.defer()将导致$ q.defer承诺在出现错误时挂起,并会造成内存泄漏。

#2


3  

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);

您甚至不需要创建新的承诺,因为$ http会返回一个承诺本身,因此您的实现是多余的。你可以这样做:return $ http(getPlayerBasic);