4

I created following controller with 2 service calling with services. Second response comes before then first. i want to do like i need first response first and second response second. but i just stuck with async and sync please help me for solving.

Second call is depends on first call. For example if first call returns 10 record then i have to call second web service 10 time taking id from first response. so i use for loop but it is not proper.

Controller

var mycompaigndata = [];

asyncService.loadDataFromUrls($http.get(WSURL + 'api/first/', 
{
    headers: 
    {
        "Authorization":'Bearer <my-token>'
    }
}))
.then(function(data)
{
    console.log(data);
});


asyncService.loadDataFromUrls($http.get(WSURL + 'api/second', 
{
    headers:
    {
        "Authorization":'Bearer <my-token>'
    }
}))
.then(function(data)
{   
    console.log(data);
});

Service

app.service('asyncService', function($http, $q) 
{
    return {
        loadDataFromUrls: function(url) 
        {
            var deferred = $q.defer();
            var urlCalls = [];

            urlCalls.push(url);

            $q.all(urlCalls)
            .then(
            function(results) 
            {
                deferred.resolve(results) 
            },
            function(errors) 
            {
                deferred.reject(errors);
            },
            function(updates) 
            {
                deferred.update(updates);
            });
            return deferred.promise;
        }
    };
});
Paresh Gami
  • 4,777
  • 5
  • 23
  • 41
  • I got id from first response perfectly just issue is calling second web service in loop with different id. – Paresh Gami Apr 20 '16 at 08:15
  • Your code doesn't show where the ID is in the first service's response, or where it should be passed into the second service. Just because you can see the IDs doesn't mean we know how your APIs work. – JLRishe Apr 20 '16 at 08:17

4 Answers4

7

To make sure the second calls are executed after the first one is finished, put the second call within then of the first call. To make multiple 'second' calls depending on the number of results of the first call, use $q.all.

asyncService.loadDataFromUrls('api/first/')
.then(function(firstData) {
    //assuming firstData is an array of 'x' items, do a call for each of these items:
    console.log('results of first call holds ' + firstData.length + ' items');
    var promises = [];
    for(var i = 0; i<firstData.length; i++){
        var id = firstData[i].id;//you can use this to pass to the second call
        promises.push(asyncService.loadDataFromUrls('api/second'));
    }
    return $q.all(promises);
})
.then(function(results) {
  //'results' is an array of results, the nth item holds the result of the 'nth' call to loadDataFromUrls
  for(var i = 0; i<results.length; i++){
    console.log('result nr. ' + i + ' :' + results[i])
  }
});

By using return $q.all(promises), you're avoiding the promise pyramid of doom, and keep a flat structure.

Your service code doesn't need to loop anymore. As a sidenote, you can shorten the code of the service and avoid using the 'explicit promise construction antipattern' (see here) like this:

app.service('asyncService', function($http, $q) 
{
    return {
        loadDataFromUrls: function(url) 
        {
            return $http.get(WSURL + url, {
                headers: {
                  "Authorization": 'Bearer <my-token>'
                }
            }).then(function(response){ return response.data; });
        }
    };
});
Community
  • 1
  • 1
fikkatra
  • 5,605
  • 4
  • 40
  • 66
  • Second call is depends on first call. For example if first call returns 10 record then i have to call second web service 10 time taking id from first response – Paresh Gami Apr 20 '16 at 07:57
  • you can use properties of the 'data' object when doing the second call. However, when you say you need to loop, i.e. do the second call multiple times, you might want to take a look at $q.all. But that's a different question. – fikkatra Apr 20 '16 at 08:08
  • Sorry. i forgot to add this on my question. Please can give answer of that? – Paresh Gami Apr 20 '16 at 08:09
  • Great help. Thank you very much :) – Paresh Gami Apr 20 '16 at 08:55
2

Your asyncService seems completely unnecessary and unuseful.

It sounds like you just need to learn how to chain promises and use $q.all correctly:

function queryApi(subUrl) {
    return $http.get(WSURL + subUrl, {
        headers: {
            "Authorization":'Bearer <my-token>'
        }
    }).then(function (result) { return result.data; });
}

queryApi('api/first/')
    .then(function (data) { 
        return $q.all(data.map(function (entry) {
            return queryApi('api/second/' + entry.id);
        }));
    })
    .then(function (results) {
         console.log(results);
    });
JLRishe
  • 99,490
  • 19
  • 131
  • 169
1

put second request inside first request promise:

 var mycompaigndata = [];

asyncService.loadDataFromUrls($http.get(WSURL + 'api/first/', 
{
   headers: 
   {
    "Authorization":'Bearer <my-token>'
   }
 }))
.then(function(data)
{
    asyncService.loadDataFromUrls($http.get(WSURL + 'api/second', 
         {
           headers:
         {
         "Authorization":'Bearer <my-token>'
          }
        }))
        .then(function(data)
        {   
         console.log(data);
    });
});
aseferov
  • 6,155
  • 3
  • 17
  • 24
  • Second call is depends on first call. For example if first call returns 10 record then i have to call second web service 10 time taking id from first response – Paresh Gami Apr 20 '16 at 08:04
  • when you write second call in the first call promise the second call will wait for first call and you can use first request data for second request – aseferov Apr 20 '16 at 08:08
1

I think the best answer is to use loop since you need to iterate the response to get the id.

asyncService.loadDataFromUrls(WSURL + 'api/first/')
    .then(function(data) {
         //iterate to get the id
           //call service again
            asyncService.loadDataFromUrls(WSURL + 'api/first/')
                .then(function(data) {
                     //code here
                });
     });

Service

app.service('asyncService', function($http, $q) {
    return {
         loadDataFromUrls: function(url) {
              return $http.get(url, {
                  "Authorization":'Bearer <my-token>'  
              });
         }
    };
});