Angular is finally not firing in controller - angularjs

I'm using a angular factory to run inside my controller, however my finally doesn't fun in the controller, it does run in the factory below is the code: factory -
var createProfile = function (profile) {
var deferred = $q.defer();
$http.post("localhost/profile", profile)
.success(function(data, status){
deferred.resolve(data);
})
.error(function(error, status){
$rootScope.error = sitesettings.parseErrors(error);
})
.finally(function(){
console.log('hello'); // **this message logs**
});
return deferred.promise;
};
and in my Controller I have this:
profileFactory.createProfile (profile)
.then(function (data) {
// **works if successful**
})
.finally(function () {
console.log('fin'); // **this never fires, successfully or on an error**
});
I guess I could pass my object into the profileFactory like profileFactory.createProfile (profile, myObject) and return it, but it seems counter intuitive.
Can somebody please advise. thank you.
kind regards

It's because you're returning a different promise, which you never manually resolve. If you just return $http.post(//etc.) it should work fine.
EDIT:
I might've spoken to soon. I missed that you were resolving in your success. But that seems unnecessary. Just do
return $http.post("localhost/profile", profile);
and have your controller attach success, error, and finally handles.

Related

Error: $injector:undef Undefined Value in angularjs

The response of ajax is like ["99636941","74167247"]. But the values are not accepted by angularjs. The response is ok. If I declare the same response as static, then it is working properly.
app.factory("States", function(){
var states;
$.ajax({
url:'php/usersList.php',
type:'post',
success:function(data,status)
{
states = data;
console.log(states);
},
error:function(xhr,desc,err)
{
console.log(xhr);
console.log("Details: "+ desc + "\n error:"+err);
}
});
return states;
});
Couple of things to note:
Do not use jQuery ajax $.ajax in angularjs service - use $http instead as it will handle digest cycle by itself. Read: https://docs.angularjs.org/api/ng/service/$http
As you are making an ajax call, return states will get executed even before your ajax success event - try looking into Promises in javascript/angular js.
You may refactor this method like:
app.factory("States", function($http){
var getStates function(){
return $http.post('php/usersList.php');//ideally this should be a GET method
};
return {
getStates: getStates
}
});
And in theplace where you call this method:
var states;
States.getStates().then(function(data){
states = data;
})
If we make it more simpler, You can do it the following way.
app.factory("States", function($http){
var factory={};
factory.getStates=function($http){
return $http({
method:'GET',
url:'your URL'
});
};
/*similarly write as many functions as you need and then simply return the factory var*/
return factory;
});

console service response inside controller

i have written a service with take parameter on the basis of which it response me with the response of http request.
this.getPaymentDueDetails=function(date){
this.getfromRemote('paymentdue/'+btoa(date))
.success(function(response){
return response;
})
.error(function(response){
return false;
})
}
getfromRemote is my another service which make http request
now i am trying to get the response of this service call inside my controller function
$scope.callDueReports=function(blockNum){
var data;
data=myAngService.getPaymentDueDetails('2015-04-20');
console.log(data);
}
its quite obvious that i wont get any thing in data as the page loads initially but i want the result of getPaymentDueDetails int it.
Please modify your service to return the promise like below.
this.getPaymentDueDetails = function(date) {
return this.getfromRemote('paymentdue/' + btoa(date));
};
And in controller check if the promise is resolved.
$scope.callDueReports = function(blockNum) {
var data;
myAngService.getPaymentDueDetails('2015-04-20').then(function(dataFromService) {
data = dataFromService;
console.log(data);
})
.catch(function(response) {
console.error('error');
});
};

q promise resolved before completed?

I think I may be missing something fundamental about how a promise works, because I never seem to be getting the result I expect, so hoping someone can correct my thinking.
In this case, it is a relatively easy call. I have a angular factory that among other things gets some data from the API (which makes a call to mongodb).
As there is a $http request (which is asynchronous), I wrapped the http call in a $q function which should return a resolve if successful and a reject if an error.
factory.loadLayout = function (layoutName) {
return $q(function(resolve, reject){
$http.get('/api/getlayout/'+layoutName)
.success(function (data) {
layout = data;
console.log("Got " + layout.name);
resolve('OK');
})
.error(function(data,status,headers,config){
reject(new Error( status));
});
});
}
I then have another function which is dependent on the data collected in the first function, called getButtonId, but as far as I can tell, and even though it is wrapped in the .then, it seems like it is called before the promise is resolved.
var promise = padArea.loadLayout(layoutName);
promise.then(padArea.getButtonId('A0'));
So what am I missing?
== UPDATE ==
So trying the same thing using q.defer
factory.loadLayout = function (layoutName) {
var defer = $q.defer()
$http.get('/api/getlayout/'+layoutName)
.success(function (data) {
layout = data;
console.log("Got " + layout.name);
defer.resolve('OK');
})
.error(function(data,status,headers,config){
defer.reject(new Error( status));
});
return defer.promise;
}
Still not working as I expect, and the function inside .then is still called before http have completed.
== UPDATE 2 ==
OK, so got it working (if I just call the function in the factory inside the .then, it calls it directly, however, if I wrap it in a function as below, it all of a sudden works. Can anyone explain why though, because to me it seems like wrapping the call to a function inside a function should make no difference from just calling the function.
padArea.loadLayout(layoutName).then(function(result){
padArea.getButtonId('A0')
});
Strangely enough, as long as I wrap the second call in ( the one inside the .then ) my original code works as well.
Just use $http promise:
factory.loadLayout = function (layoutName) {
return $http.get('/api/getlayout/'+layoutName)
.success(function (data) {
layout = data;
console.log("Got " + layout.name);
resolve('OK');
})
.error(function(data,status,headers,config){
reject(new Error( status));
});
}
And then to use it...
factory.loadLayout(param).then(function (response) { ... });
OR
I see what you are trying to do. Instead create a deffered from $q
factory.loadLayout = function (layoutName) {
var defer = $q.defer();
$http.get('/api/getlayout/'+layoutName)
.success(function (data) {
layout = data;
console.log("Got " + layout.name);
defer.resolve('OK');
})
.error(function(data,status,headers,config){
defer.reject(new Error( status));
});
return defer.promise;
}
You could also use $q.defer():
deferred = $q.defer();
$http.get('/api/getlayout/'+layoutName)
.success(function (data) {
layout = data;
deferred.resolve("OK");
})
.error(function (data,status,headers,config){
deferred.reject(new Error(status));
})
return deferred.promise;
This can be a little more general if you're not just doing an http request, and lets you control the return.

AngularJS - why promises ($q) with $http?

I am learning AngularJS after converting from jQuery for a few years. And some bits are much more intuitive. Some not so much :).
I am trying to get my head around the use of promises, particularly $q in use with $http and there does not seem to be too much information around these two combined that I can find.
Why would I use promises in place of the success/error callback? They both make uses of callbacks in reality, so why is a promise considered better? E.g. I could set up a get(...) function like follows:
function get(url, success, error) {
success = success || function () {};
error = error || function () {};
$http.get(url)
.success(function (data) {
success(data);
})
.error(function (error) {
error(error);
});
}
get('http://myservice.com/JSON/',
function () {
// do something with data
},
function () {
// display an error
}
);
Which is good(?) because it gives me complete control over what is happening. If I call get(...) then I can control any success/errors wherever get is called.
If I convert this to use promises, then I get:
function get(url) {
return $http.get(url)
.then(function (data) {
return data;
},
function (error) {
return error;
});
}
get('http://myservice.com/JSON/')
.then(function (data) {
// do something with data
});
// cannot handle my errors?
Which is condensed, I agree; we also do not have to explicitly worry about the success/error callback, but I seem to have lost control over my error callback for a start - because I cannot configure a second callback to handle an error.
Which means that if I use this function in a service which can be used by multiple controllers, then I cannot update the UI to alert the user to an error.
Am I missing something? Is there a reason why promises is preferred? I cannot find an example why.
Usually you'll deal with asynchronous tasks in Javascript with callbacks;
$.get('path/to/data', function(data) {
console.log(data);
});
It works fine, but start to complicate when you go into whats called the 'callback hell';
$.get('path/to/data', function(data) {
$.get('path/to/data2' + data, function(data2) {
$.get('path/to/data3' + data2, function(data3) {
manipulate(data, data2, data3);
}, errorCb);
}, errorCb);
}, errorCb);
The alternative is working with promises and defered object;
Deferreds - representing units of work
Promises - representing data from those Deferreds
Sticking to this agenda can assist to you in every extreme asynctask case:
You have a regular call that need to get data from the server, manipulate it, and return to the scope
You have multiple calls that each is depending on the precious one (cahin strategy)
You want to send multiple (parallel) calls and handle their success in 1 block
You want your code to be orginized (prevent dealing with handling results on controllers)
Your task is the easiest one to handle with $q and $http
function get(url) {
var deferred = $q.defer();
$http.get(url)
.success(function (data) {
deferred.resolve(data);
})
.error(function (error) {
deferred.reject(error);
});
return deferred.promise;
}
And calling the service function is the same
get('http://myservice.com/JSON/')
.then(function (data) {
// do something with data
});
// cannot handle my errors?
You can handle the error like this:
get('http://myservice.com/JSON/')
.then(function (data) {
// do something with data
},
function (error) {
//do something with error
});
But unfortunately since you have already caught the error then the final error won't be triggered. You will also have the same problem with success.
To get that to work you ned to use $q.
function get(url) {
var deferred = $q.defer();
$http.get(url)
.success(function (data) {
deferred.resolve(data);
})
.error(function (error) {
deferred.reject(error);
});
return deferred.promise;
}
Also there is no need to pass in success and error functions because you can use promises instead.

how to make synchronous http request in angular js

How to make blocking http request in AngularJS so that i can use the $http response on very next line?
In the following example, $http object doesn't return the result to the next line so that I can pass this result to fullcalender(), a JavaScript library, because $scope.data returns blank value.
This is the sample code:
$http.get('URL').success(function(data){
$scope.data = data;
});
$.fullCalender({
data: $scope.data
});
You can use promises for that.
here is an example:
$scope.myXhr = function(){
var deferred = $q.defer();
$http({
url: 'ajax.php',
method: 'POST',
data:postData,
headers: {'Content-Type': 'application/x-www-form-urlencoded'}
})
//if request is successful
.success(function(data,status,headers,config){
//resolve the promise
deferred.resolve('request successful');
})
//if request is not successful
.error(function(data,status,headers,config){
//reject the promise
deferred.reject('ERROR');
});
//return the promise
return deferred.promise;
}
$scope.callXhrAsynchronous = function(){
var myPromise = $scope.myXhr();
// wait until the promise return resolve or eject
//"then" has 2 functions (resolveFunction, rejectFunction)
myPromise.then(function(resolve){
alert(resolve);
}, function(reject){
alert(reject)
});
}
You can't, you'll need deal with it through promises, but you could try do it like this:
$http.get('URL').success(function(data){
angular.copy(data, $scope.data);
});
$.fullCalender({
data: $scope.data
});
but most people would just do
$http.get('URL').success(function(data){
$.fullCalender({
data: data
});
});
If whatever your fullCalender object is doesn't work with async data, you might need to wrap it in something like ng-if or force it to redraw when the data has been supplied. You can also force the controller to not load until the data is loaded by using the route resolve.
Here is a practical answer, courtesy of user Kirill Slatin who posted the answer as a comment. Practical use example at the bottom of the answer.
If, like me, you need to use that response object as a scope variable, this should work:
$http.get('URL').success(function(data){
$scope.data = data;
$.fullCalender = $scope.data;
$scope.$apply()
});
$scope.$apply() is what will persist the response object so you can use that data.
-
Why would you need to do this?
I'd been trying to create an "edit" page for my recipes app.
I needed to populate my form with the selected recipe's data.
After making my GET request, and passing the response data to the $scope.form, I got nothing... $scope.$apply() and Kirill Slatin helped big time. Cheers mate!
Here's the example from my editRecipeController:
$http.get('api/recipe/' + currentRecipeId).then(
function (data) {
$scope.recipe = data.data;
$scope.form = $scope.recipe;
$scope.$apply()
}
);
Hope that helps!

Resources