1

Struggling to understand the concept of http requests and promises. I know the http request is asynchronous but have no idea how to implement a promise and return the data to update the $scope variable so that is accessible anywhere.

At the minute the $scope variable only prints out inside '.then'

Basically i'm trying to return the 'season_number' into an array so its displayed as:

Array[

{season_number: 1},
{season_number: 2},
{season_number: 3},
{season_number: 4},
{season_number: 5}

];

Code:

$scope.seasonDetails = [];

var getSeasons = function() {
var data = "";
 $http({
    method: 'GET',
    url: url

  })

  .then(function(response) {
    var tvSeasonDetails = [];
    for (var i = 0; i < response.data.seasons.length; i++) {
      tvSeasonDetails.push(response.data.seasons[i].season_number)
    }

    $scope.seasonDetails = tvSeasonDetails;
    console.log($scope.seasonDetails); //<----Variable displayed here

  })
}

  getSeasons();
  console.log($scope.seasonDetails); //<---- Empty Array displayed here
Barlow96
  • 57
  • 8
  • 3
    Possible duplicate of [How do I return the response from an asynchronous call?](http://stackoverflow.com/questions/14220321/how-do-i-return-the-response-from-an-asynchronous-call) – Sven Mar 23 '17 at 23:50

2 Answers2

4

As you pointed out, $http.get() is asynchronous. So when you call getSeasons, it will not set the value of $scope.seasonDetails right away, but only after it receives a response.

So, yes, it won't be available in your call to console.log right after your call to getSeasons, but it will eventually get there once it's available.

If you just need the data to get in scope at some point (so it can be displayed in your page via ng-repeat or the like), then you don't need to do anything more. Angular will apply the changes when they arrive.

If you do need to manipulate the results, then you can either do it directly in the existing then, or have getSeasons return the $http promise, and add a new then after your call to getSeasons. Which is more relevant depends on your actual needs (e.g. getSeasons is called from several places but you have different post-processing depending on where it's called from or not).

Option 1:

var getSeasons = function() {
var data = "";
 $http({
    method: 'GET',
    url: url

  })

  .then(function(response) {
    var tvSeasonDetails = [];
    for (var i = 0; i < response.data.seasons.length; i++) {
      tvSeasonDetails.push(response.data.seasons[i].season_number)
    }

    $scope.seasonDetails = tvSeasonDetails;
    console.log($scope.seasonDetails); //<----Variable displayed here

    ... add your call to any function that needs access to $scope.seasonDetails here...
  })
}

Option 2:

var getSeasons = function() {
var data = "";
 // the only change is right here
 return $http({
    method: 'GET',
    url: url
  })

  .then(function(response) {
    var tvSeasonDetails = [];
    for (var i = 0; i < response.data.seasons.length; i++) {
      tvSeasonDetails.push(response.data.seasons[i].season_number)
    }

    $scope.seasonDetails = tvSeasonDetails;
    console.log($scope.seasonDetails); //<----Variable displayed here

  })
}

getSeasons().then(function()
{
   ... your call to whatever function needs $scope.seasonDetails here ...
});
jcaron
  • 17,302
  • 6
  • 32
  • 46
  • I need to use '$scope.seasonDetails' in a function directly after this, but is always giving an empty array – Barlow96 Mar 23 '17 at 23:56
  • Then either move the call to that function inside your existing `then`, or have `getSeasons` return a Promise (i.e. `return $http.get(...)`), and either call that function inside a `then` of this (i.e. `getSeasons().then(function() { youcallhere })` or pass the promise to this function so it can then do the `then` itself. – jcaron Mar 24 '17 at 00:00
  • Edited answer with two options. – jcaron Mar 24 '17 at 00:03
1

In the case where you need to manipulate some results after seasonDetails has changed, you can use the function $scope.$watch(...)

 $scope.$watch('seasonDetails', function(newValue, oldValue) {
      console.log($scope.seasonDetails);
 });
Andrew Shepherd
  • 44,254
  • 30
  • 139
  • 205
  • 1
    Wouldn't a `$watch` add way more overhead than just a `then` on a Promise? – jcaron Mar 24 '17 at 00:04
  • @jcaron I agree with you on this, there's no need to pollute your code with $scope.$watch unless it's a last resort when Promises can't achieve what you need. – Ben Mar 24 '17 at 00:51