What is the right way to chain calls to services in AngularJS? - angularjs

I need to invoke a Restful service endpoint to get an Id and once I got the result I should invoke a second Restful service endpoint through a angularjs service.
First call returns a customer ID, with this customer ID I need to search for additional info about that customer.
As I should call and and wait for promises I don't think nesting calls to promises is a good pratice. What I mean is that something like the below code isn't supposed to be a neat solution. Am I right or wrong? What should be a good way to achieve this task.
someService.someAction().then( function(data){
var id = data.data;
antoherCallToAnotherService.someOtherAction(id).then(function(data2){
//do some stuff
);
);
Thank you

This is quite typical approach. However, you can optimise it by chaining multiple promises:
someService.someAction().then(function(response) {
var id = response.data;
return antoherCallToAnotherService.someOtherAction(id);
})
.then(function(data2) {
// data is available
});
This is not that bad at all, however can be improved even more if you want. You should probably not make the first promise resolve with entire response object, underlying service should resolve with actual (maybe processed data). Then your code could become:
someService.someAction()
.then(antoherCallToAnotherService.someOtherAction)
.then(function(data) {
// data is available
});
For above to work, someService.someAction should resolve with response.data (which is an id in your case).

Related

How to Execute Multiple post request simultaneously using angular js 1

I need to post same url with multiple parameters simultaneously .
how to achieve in angular 1
You do it with $http service with $http.post() request. If you want to do multiple requests, you can do it a loop. E.g. return $http.post(url,data).then((response)=>{return response.data;})
This is where you need to clarify what do you mean by saying "simultaneously", because if you want to receive the response from all of these requests at the same time, then you need something more advanced like deferred objects. This is what $q service is for, it helps you to resolve such Promises.
Firstly you need to collect all of the asynchronous callbacks in an array:
var promises = [];
angular.forEach(array, function(element) {
promises.push( $http.post(url,element).then((res)=>{return res.data}) );
}
(Pass different parameters/data however you like)
Then you need to resolve all of them at the same time with $q.all():
$q.all(promises).then((res)=>{
/* do what you need with them, e.g:
$q.defer().resolve(res)
*/
})
It should resolve an array with your data from previous requests in synch now.

Sending a promise from one controller to another in Angular

In my web app, I would like to load all of the user data at the beginning, in the run method and pass the data to the other controllers to be shown to the user in the dashboard.
So lets say I have a data structure on the server
data = {
x : 30,
y: 20
}
I would like to get it in one http requests (instead of creating multiple http requests and creating multiple promises)
The http request I run in the run method of the app
service.getDataFromServer = function(){
return $http.get('/admin/data').then(function(response) {
data = response.data;
});
};
This will create a promise.
I would like to take this promise and pass it to other controllers to be used.
My first question is how can I do it so the data from the promise will bind to the data I am about to show to the user.
The second question is, can I use the structure fields before the promise is even resolved?
for example
$scope.x = data.x
And by data I mean the data which is about to be resolved
Thanks
I would like to get it in one http requests (instead of creating multiple http requests and creating multiple promises)
After getting response from http call,save the data in factory/services so,you can use is at another location like controller in your case by injecting it which is most recommended.
I would like to take this promise and pass it to other controllers to be used.
how can I do it so the data from the promise will bind to the data I am about to show to the user.
make http call and save the promise.
service.getDataFromServer = function() {
var promise = $http.get('test.json');
service.savePromise(promise);
}
and
get saved promise.
.controller('testCtrl', function(service) {
service.getSavedPromise().then(function(response){
console.log(response.data)
})
})
Plunker here
The second question is, can I use the structure fields before the promise is even resolved? for example
$scope.x = data.x
// data is still undefined as promise is not resolved.so,you will get TypeError
What you can do best here,you can merge data to your existing data object/array,so,Angular two way binding can do rest of the things for you.

Angularjs factory method implementation

I am writing an angularjs factory to do some calculation. I named it as CalcEngineService This factory has one method which is used by controllers,directives. This factory method is called several hundreds of times.
My question is that the factory method requires collection of rules to do the calculation. I get this collection of rules from http service.When I use http call to get rules in side the method I see several hundreds of http calls and the performance is affected. How can I restrict the call to get rules collection to just once and also make sure any change to rules is also taken care of.
defaultRules = [];
function calculateDuedate(test) {
getDefaultRules().then(function(rules){
// DO calculations with rules and find the duedate and update test with duedate
});
return test.dueDate;
}
function getDefaultRules() {
return $q(function (resolve, reject) {
if (utility.isEmpty(defaultRules)) {
rulesService.getDefaultRules().then(function (rules) {
defaultRules = rules.data;
resolve(defaultRules);
});
}
else {
resolve(defaultRules)
}
});
}
I am fairly new to angularjs and dont know many features fully to take advantage of. Can anybody suggest a good way of handling this ?
You'll need to add some logic around your $http call, specifically once you've made one request don't make anymore. Wait for the one request to return and then continue your calculations.

Use return data from an angular service resource across all controllers with only one call

I have a custom Web API written in .NET that returns user's information that will be used in my AngularJS application. I want to be able to call my API once, and then use that returned JSON across my entire AngularJS application without having to recall the API within each of my controllers.
I currently have a factory of services, one of which returns all of the client's details I need to use the in rest of the services.
.factory('customApiService', function ($resource) {
return {
userInfo: function(userId, callback){
var api = $resource('../../api/UserInfo/:userId', {
userId: userId
}, {
fetch: 'JSONP',
'query': { isArray: false }
});
api.fetch(function (response) {
callback(response);
});
}
}
)
Now I don't want to call this userInfo service in every controller, but I do want the data to be passed into each without calling my API multiple times.
customApiService.userInfo(userId, function (d) {
var gaProfileId = d.gaProfileId;
var yelpId = d.yelpId;
var tripAdvisorId = d.tripAdvisorId;
var facebookPageName = d.facebookPage;
var twitterHandle = d.twitterHandle;
var clientName = d.clientName;
var searchlightAccountId = d.searchlightAccountId;
var searchlightDomain = d.searchlightDomainId;
}
You can try global variables .
use a $rootScope https://docs.angularjs.org/guide/scope
$rootScope is available in all controllers an templates .Just inject $rootscope in your controller or wherever required.
From what I read of your description and responses to other questions, it sounds like you're trying to make an asynchronous call before the rest of your app starts up. This is possible, but complex, and sort of voids the point of Angular in the first place. As I see it, you have two options:
QUICK HACK: If you really want this kind of behavior, why start your app at all? Do your request first, before you define your app in the first place, then define your app in the result handler for the request.
RIGHT WAY: Alter the behavior of your services and controllers to tolerate not having enough information to fully start. A lot of times this is less difficult than it sounds. Usually you can just chain a promise into their initialization block of code to wait for the data you need. Take a look at Brian Ford's "Angular Modal" project, at the lines of code I've highlighted here:
https://github.com/btford/angular-modal/blob/master/modal.js#L25-L36
This technique sets up a promise to return from the function. If the data it needs is already loaded from the service, it resolves the promise immediately. Otherwise, it makes the call to get what it's after, and you can see later (line 39) that the module uses promise.then() to wait until it has the data it needs to run.
This is a great pattern for both controllers and services when working with asynchronous data.
If using a $resource call instead, note that most $resource calls return a promise in a property called $promise. You can do something like this:
var MyController = function($scope) {
// This will get set soon!
$scope.myData = null;
var myResource = $resource('/path/to/:someId', { someId: '#id' });
myResource.get({ someId: 1 }).$promise.then(function(data) {
$scope.myData = data;
});
};
You can do more things in the .then() resolution callback for the promise, like initialize more parts of your controller, etc. There are also ways you can delay starting your entire controller until the resource is available. One really cool way is if you happen to be using the Angular ui-router module, there is a "resolve" option when defining each route. You can use that to call the $resource as shown above, and ui-router will wait to start your controller/view until it has what it needs.

Track progress of facebook graph api requests

I am willing to track the progress of the querying from Facebook's graph api. I have this promise in an angular service
getPosts: function() {
var deferred = $q.defer();
FB.api(
"/me/home", {since:'yesterday','limit': limit},
function ( response ) {
if ( response && !response.error ) {
deferred.resolve(response);
}
}
);
return deferred.promise;
},
and in my controller I use FBS.getPosts().then(function (data) {...}); . I am willing to be able to keep track of the progress of this promise and be able to display it on my page. Any ideas if this is even possible? I tried adding function (progress) , after the error function of the promise in my controller, had no luck though. Somewhere I read you can use .progress(function (progress){...}) like the .then one but it didn't work.
I don't like leaving questions in the promise tag open as I've made is a personal goal to keep it clean :) so here goes:
Facebook does not expose that functionality, if you want you can track the progress of multiple requests (that is, how many out of N requests are done) but that's not the same thing.
What you are asking for is simply put - impossible. There is no way to know how far the query has progressed without Facebook telling you, and they're not telling you.
Happy coding.

Resources