azizmars azizmars - 2 months ago 12
AngularJS Question

Variable remaining undefined after being set in a get call

Hey guys I'm attempting to learn how to develop with AngularJS and the MEAN stack. I'm very much so a beginner developer, so this might be a lack of knowledge issue.

So in the following code, I preset my variable, $rootScope.sprintStart & $rootScope.taskPopAgain, after running it through the get call I attempt to store a value to it. If I do a console.log while its in the get call, the value comes back as expected, the next line after the get call the value is gone. What am I doing wrong here?

Values coming from the api/tasks is an array with objects in it, and api/sprint models should be sending a single object.

I'm aware that I can clean up and simplify my variables up, the reason I have them way it is right now is because it helps me visualize what is happening. Once again, I'm a beginner lol.

Thanks for the help guys!



'use strict';

angular.module('inBucktApp')
.service('VariableService', function () {
// AngularJS will instantiate a singleton by calling "new" on this function
var ticketId = 'noTicketYet';
var ticketAssigneeName = 'noTicketNameYet';

return {
getPropertyId: function () {
return ticketId;

},
getPropertyName: function () {
return ticketAssigneeName;

}
,
setProperty: function(value, valueName) {
ticketId = value;
ticketAssigneeName = valueName;
}
};
})
.run(['$rootScope', '$http', 'socket', 'VariableService', function($rootScope, $http, socket, VariableService) {


$rootScope.sprintStart;
$rootScope.taskPopAgain;

$http.get('/api/sprints').success(function(sprints) {

$rootScope.sprints = sprints.pop();

$rootScope.sprintStart = new Date($rootScope.sprints.start);
$rootScope.sprintEnd = new Date($rootScope.sprints.end);

console.log($rootScope.sprintStart)

socket.syncUpdates('sprints', $rootScope.sprints);
});

$http.get('/api/tasks').success(function(task) {
$rootScope.task = task;
$rootScope.taskPop = _.flatten($rootScope.task);
$rootScope.taskPopAgain = $rootScope.taskPop.pop();
console.log($rootScope.task);
// console.log($rootScope.taskPop);
console.log($rootScope.taskPopAgain.start);
console.log($rootScope.taskPopAgain);
socket.syncUpdates('task', $rootScope.task);
});

//coming up as undefined now, so function below doesnt work.
console.log($rootScope.taskPopAgain);
console.log($rootScope.sprintStart);




Answer

This is a common problem for beginners. You are missing the idea that the $http method is asyncronous. Your calls to console.log are occurring before the $http method has finished executing. Inside your success method, you are doing everything correctly, but by that time, your console.log messages have already executed. Run your app in a debugger and you will see that this is true.

    // step 1: this code executes
    $http.get('/api/tasks').success(function(task) {
      //step 3: finally this, when the api responds
      $rootScope.task = task;
      $rootScope.taskPop = _.flatten($rootScope.task);
      $rootScope.taskPopAgain = $rootScope.taskPop.pop();
      console.log($rootScope.task);
      // console.log($rootScope.taskPop);
      console.log($rootScope.taskPopAgain.start);
      console.log($rootScope.taskPopAgain);
      socket.syncUpdates('task', $rootScope.task);
    });

    //step 2: then this
    //coming up as undefined now, so function below doesnt work.
    console.log($rootScope.taskPopAgain);
    console.log($rootScope.sprintStart);

If you place a breakpoint at the $http call, the console.log call at the bottom, and one inside the success method you will see the order of execution is not what you expected.

So, basically, anything you want to do with the data returned from the $http call, you will need to do INSIDE the success call.

To solve your problem you would do somthing like this:

$http.get('/api/tasks').success(function(task) {
  $rootScope.task = task;
  $rootScope.taskPop = _.flatten($rootScope.task);
  $rootScope.taskPopAgain = $rootScope.taskPop.pop();
  myFunction();
});

function myFunction() {
  // do something with here
  console.log($rootScope.taskPropAgain); // this will not be undefined
}