2

I am trying to use the $q service inside my controller. I have multiple environment which I need to hit and collect the data and consolidate the data and then put inside the scope. I have the below code.

     var results=[];
     for(var environment in  $rootScope.envs){
       $http.get(callService.getDomainUrl()+'/'+$rootScope.envs[environment]+ '/hosts.json').success(function(data){
              results.push(data)
          })
      }

      $q.all(results).then(function(){
          console.log(results);
      })

However, I am not sure if this is the right approach and also I need to map the result into an object of the below type:

results:{
  env1: { // result data for env1},
  env2: { // result data for env2},
  env3: { // result data for env3},
}

How to resolve the promise and consolidate the data in the above format.

zilcuanu
  • 3,451
  • 8
  • 52
  • 105

2 Answers2

1

You should check this example(look at log). I simulate $http.get request by means of setTimeout function.

Slava Utesinov
  • 13,410
  • 2
  • 19
  • 26
  • This is what i was looking for. If there is an error, what is the best way to handle the error condition for any of the environment? – zilcuanu Jan 11 '16 at 09:38
  • Also the results object now contains the data and not with the key mapped to the environment name. I want the output to be in { env1: {data1}, env2: {data2}, env3: {data3}, env4:{data4}} – zilcuanu Jan 11 '16 at 09:43
  • I correct my answer - shifted `var prom = $q.defer();promises.push(prom);`. And can you write what you fetch at your console: `console.log(results);` – Slava Utesinov Jan 11 '16 at 09:46
  • And I added code for error processing, please look at new code! – Slava Utesinov Jan 11 '16 at 09:53
  • This is an antipattern. You can use `$http.get` promise w/o create new one. – vp_arth Jan 11 '16 at 09:59
  • when I console the log, I am getting the data for only one call. I am able to see all the calls being made but I am seeing only one value in the console. The rest three result data is not populated in the `results` object. Is there something wrong? – zilcuanu Jan 12 '16 at 08:30
  • Yes I made one mistake - I added to array of `promises` not actual promises, but the result of $q.defer(), that was wrong, please, look at example. – Slava Utesinov Jan 12 '16 at 09:33
1

As an addition to @SlavaUtesinov answer.
You should not to create new promises with $q.defer, just use $http.get return.

You'll get something like this:

  $q.all(Object.keys($rootScope.envs).map(request)).then(function(res){
    var results = {};
    for (var env in res) {
      results[env] = res[env].data;
    }
    console.log(results);
  }, function(err){
    console.error(err);
  });

  function request(env) {
    return $http.get(callService.getDomainUrl()+'/'+$rootScope.envs[env]+ '/hosts.json');
  }

Anyway, $q.all combine array/hash of promises into a single promise.
So, you should collect promises before call it.

vp_arth
  • 14,461
  • 4
  • 37
  • 66
  • The above code works absolutely fine. However, the results object contains all the response from four environments. I need to map the response of each envrionement against its name. How can we get this done in the format of response={[{env1: {env2-res object}}, {env2: {env2-res object}, {env3: {env3-res object}}]} – zilcuanu Jan 12 '16 at 08:47
  • If you pass hash object with promises to `$q.all` original keys will be saved in the result. You should pass `{'env1': request('env1'), env2: request('env2')}` hash to achieve this. – vp_arth Jan 13 '16 at 13:54