-1

I make a few different $http calls and I want to set either variable (var blah) or $scope to be set to an object value and persist at least down a few lines so that it can be sent to a 2nd $http request

I get undefined , why and how to fix / persist the variable or scope?

app.controller('detailController', function ($scope, $interval, $http, $routeParams, $window, sessionVariables, $httpParamSerializer) {

//$scope.xid = 1;  // this seems to persist  but NOT if i try update it in 1st $http.get

$http.get('/Umbraco/Api/ClientsApi/GetClient/' + clientId).
success(function (data, status, headers, config) {
    console.log(data); // correctly shows me object of data
    $scope.xid = data.Id;  // DOES NOT WORK OUTSIDE OF this $http.get
    console.log(data.Id); // yes shows data inside here
    //console.log(data.IsSampleData); // contains data 
    $scope.client = data;  // this is how is then use client object in view template

}).
error(function (data, status, headers, config) {
    // log error
});

This is the problem, $scope.xid does is saying undefined

console.log('before');
console.log($scope.xid);  
console.log('after');

Of which this 2nd $http.get call I want to append the xid onto the end of it

$http.get('/Umbraco/Api/ActivityApi/GetActivity').
    success(function (data, status, headers, config) {

   $scope.activity = data;  // correctly gets data

 }).
 error(function (data, status, headers, config) {
   // log error
 });

Update : FULL CODE

app.controller('detailController', function ($scope, $interval, $http, $routeParams, $window, sessionVariables, $httpParamSerializer) {

    var clientId = $routeParams.id;
    //console.log(clientId);

    //$scope.xid = 1;

    $http.get('/Umbraco/Api/ClientsApi/GetClient/' + clientId).
    success(function (data, status, headers, config) {
        console.log(data);

        //console.log(data.Id);
        //console.log(data.IsSampleData);
        $scope.client = data;

    }).
    error(function (data, status, headers, config) {
        // log error
    });

    console.log('before');
    console.log(client.Id);
    console.log('after');

    $http.get('/Umbraco/Api/ActivityApi/GetActivity').
   success(function (data, status, headers, config) {
       //console.log(data);
       //console.log(data.IsSampleData);
       $scope.activity = data;

   }).
   error(function (data, status, headers, config) {
       // log error
   });


});
  • `$scope.xid = data.Id; // DOES NOT WORK OUTSIDE OF this $http.get` - this is because `data` is not available outside of the get. Now, what is the problem? For the second code block, where are you running that code? – tcooc Oct 25 '16 at 18:53
  • In same controller ( 2nd code block , ALL the code is in same controller... I simply made comments –  Oct 25 '16 at 19:02
  • 1
    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) – Heretic Monkey Oct 25 '16 at 19:04
  • Avoid using success() an error methods() since they are deprecated since v1.4.12. (Look for 'Deprecation notice' on https://code.angularjs.org/1.4.14/docs/api/ng/service/$http ) – rtribaldos Oct 25 '16 at 19:12

5 Answers5

0

use then() for $http according to official documentation

 $http.get('/Umbraco/Api/ActivityApi/GetActivity').then(
    function success(response) {
       console.log(response.data);
       console.log(response.data.Id);
       $scope.client  = response.data; 
    },
    function error(response) {
      console.log(response);
    }
 );

EDIT !

Http is asynchronous, it take some time to do it. It mean that $http is called, and the answer IS NOT WAITED. the code after it is runned immediatly !

console.log("before $http");
$http.get('/Umbraco/Api/ActivityApi/GetActivity').then(
    function success(response) {
       console.log("http success"); 
       $scope.client  = response.data; 
    },
    function error(response) {
      console.log("http error"); 
      console.log(response);
    }
 );
 // this will be logged before the success/error of http
 console.log("after $http");

If you want to do something when success is done, create a function for it and call it from success/error

AlainIb
  • 4,544
  • 4
  • 38
  • 64
0

You are setting $scope.xid once the promise returnet by $http.get() is resolved.

Actually the console.log($scope.xid) executes before than the assignment!


If you want to use the result of a first promise, you can chain promises like this:

$http.get('/Umbraco/Api/ClientsApi/GetClient/' + clientId)
.then(function(response) {
  return $http.get('/Umbraco/Api/ActivityApi/GetActivity' + response.Id)
)
.then(function(response2) {
  // Proccess response2
});
rtribaldos
  • 1,177
  • 14
  • 28
0

Use Promises and chaining

var firstRequest = $http.get(url).then(function (result) {
  /* optional - do something with result, pass through to next .then() */
  return result;
});

var secondRequest = firstRequest.then(function (result) {
  return $http.get(otherUrl);
});

var thirdREquest = secondRequest.then(function () {
  /* and so on */
});
William B
  • 1,411
  • 8
  • 10
  • That is one good solution William. thank you. However is there any way that I can set a global variable like `var globalclientId = data.Id;` or `$scope.xid = data.Id` as YES i know "global variables are "bad" but i'm inside this controller and I just simply want to be able to set variables to a value ( yes and that value i understand is in the async success function of the FIRST $http.get –  Oct 25 '16 at 19:28
  • Setting the data within the controller is fine & not bad practice, just as shown `$scope.xid = data.Id`, and it will automatically reflect in the HTML template. If you need to access the data within the JS, you have to chain to the Promise with .then – William B Oct 25 '16 at 19:31
  • ughh - makes me a bit sad and frustrated that i "have" to do that , don't get me wrong , sometimes with jquery i chained because 2nd and 3rd and 4th api calls depended on one another and actually as i type this i'm realizing that the 2nd one is truly dependent on the 1st one... oops on my part .. However there are certainly going to be cases in which something you could want several async calls being made without worrying about which completes first so i suppose in some situations there could be a need for a global variable - hmmm i'm starting to answer my own questions thx –  Oct 25 '16 at 19:39
  • Promises do not have to execute in a single chain, you can kick off several promises without knowing what the resolution order would be. If you look at how I defined the promises in my example, I explicitly define `secondRequest` as happening after the `firstRequest` promise, because you mentioned that was your requirement. – William B Oct 25 '16 at 19:42
  • Here is an example of concurrent promises: https://jsfiddle.net/u91e6m79/ – William B Oct 25 '16 at 19:48
  • I do like your approach, however I am wondering if the answer to my own question that I provided is something that is indeed "working" but is it more than just an eye soar or something worse than I'm not considering? –  Oct 26 '16 at 04:31
  • your solution is fine, and would be preferrable if the getActivity method were needed seperate from the first function. for idiomatic use of promises I'd have `getActivity` `return $http.get(...)` so that the getActivity function itself becomes a promise that can be chained to. and then have the original function which calls $scope.getActivity also return the result of that call, so the whole thing can be cleanly chained to if needed – William B Oct 26 '16 at 04:37
  • Hey William I was creating a service and it does seem to be requires keyword `this` in defining my function - if you have a chance to take a quick look at my new question http://stackoverflow.com/questions/40254180/angular-service-created-function-needs-this-keyword –  Oct 26 '16 at 05:12
0

try this:

app.controller('detailController', function ($scope, $interval, $http, $routeParams, $window, sessionVariables, $httpParamSerializer) {

  var clientId = $routeParams.id;
  //console.log(clientId);

  //$scope.xid = 1;

  $http.get('/Umbraco/Api/ClientsApi/GetClient/' + clientId).then(function (response) {
    console.log(response.data);

    //console.log(response.data.Id);
    //console.log(response.data.IsSampleData);
    $scope.client = response.data;

    // second HTTP call with chained client ID received from the first call
    $http.get('/Umbraco/Api/ActivityApi/GetActivity/' + response.data.Id).then(function (response2) {
      //console.log(response2.data);
      //console.log(response2.data.IsSampleData);
      $scope.activity = response2.data;
    }).catch(function (error) {
      // log error
    });
  }).catch(function (error) {
    // log error
  });

  // this code is outside of $http promise as it is executed before promise resolve
  // so, at this point $scope.client.Id is undefined
  //console.log('before');
  //console.log($scope.client.Id);
  //console.log('after');
});
Andriy
  • 14,781
  • 4
  • 46
  • 50
0

This code does seem to "work" Any reason why I should NOT do this?

$http.get('/Umbraco/Api/ClientsApi/GetClient/' + clientId).
      success(function (data, status, headers, config) {
            $scope.client = data;
            $scope.getActivity(data);     // CALL HERE 
}).
error(function (data, status, headers, config) {
    // log error
});

$scope.getActivity = function(data) {
    $http.get('/Umbraco/Api/ActivityApi/GetActivity').
        success(function(data, status, headers, config) {
            $scope.activity = data;
        }).
        error(function(data, status, headers, config) {
            // log error
        });
};
  • the official documentation is pretty clear : `$http.get( ).then( function success(response) {},function error(response) {} );`. Don't try to re-invent the wheel. Your syntax maybe work (i didn't try it) now in this case but it it not guaranted to work when you update Angular or in other case – AlainIb Oct 26 '16 at 07:03