Angular JS 1.X Access Resolved Promise Objects values - angularjs

I have read a lot of posts on promises,resolving promises, and accessing the data however I cannot seem to. Following some posts on Stack Overflow has just caused errors, so I am not sure what exactly I am doing wrong.
I have a function like so:
function getJsonl() {
var deferred = $q.defer();
$http({
url: 'urlNotShownForSecurity',
dataType:"json",
method: 'GET',
data:{"requestId":"123"},
headers:{"Content-Type":"application/json","requestId":"123"},
}).success(function(data) {
deferred.resolve(data);
console.log(data)
}).error(function(error,status,headers,config) {
deferred.reject(error);
});
return Promise.resolve(deferred.promise);
}
Here I return a json promise that has been resolved resulting in a json object I believe.
Printing to console I get the following:
Inside data is the information I need, it looks like this:
data:Array[8]
0:Object
description:"My description paragraph"
I have tried things with the returned object in my controller like:
vm.result = data.data[0].description;
vm.result = data[0].description
I have tried many different approaches in the view as well to access but I get 2 blank li tags and that is it.
I would like to be able to access the data so I populate a table. So if I can use it with ng repeat that would be great, as well as being able to access without because some data is used in more than just the table.
Update
#DanKing, following your implementation I get the following output in console:
Now I am back with a promise object.

It looks to me as though you're fundamentally misunderstanding the nature of promises.
$http() is an asynchronous function - that means it doesn't complete straight away, which is why it returns a promise.
It looks to me as though you're trying to call $http() and then get the result back and return it from your getJson1() method, before $http() has finished executing.
You can't do that. Your getJson1() method should just return the promise, so your calling method can chain onto it - like this:
getJson1().then(function(data) {
// do some other stuff with the data
});
The whole point of promise chains is that they don't execute straightaway - instead you provide callback functions that will be executed at some indeterminate point in the future, when the previous operation completes.
Your getJson1() function just needs to do this:
return $http({
url: 'urlNotShownForSecurity',
dataType:"json",
method: 'GET',
data:{"requestId":"123"},
headers:{"Content-Type":"application/json","requestId":"123"},
});

getJsonl().then(function(data){
console.log(data);
},function(err){
console.log(err);
})
should work. Where is your $http request and where is your call to getJsonl() will also make a difference. So choose that carefully when implementation. If you are using this in a service then you will have to return the function result say
this.somefunction = function (){
return getJonl();
}
and in your controller inject the service and do the following
service.somefunction().then(function(data){
console.log(data);
},function(err){
console.log(err);
})

Ok, rewrote the answer as a complete component to show the moving parts.
$http returns a promise so your original getJsonl call can be simplified. Using your original $http parameters this should dump your API response to the screen if you use the <json-thing> tag:
angular.module('yourModuleName')
.component('jsonThing', {
template: '<pre>{{$ctrl.thing|json}}</pre>',
controller: function ($http) {
var $ctrl = this;
getJsonl()
.then(function (response) {
console.log(response); // we have the $http result here
$ctrl.thing = response.data; // allow the template access
}, function (error) {
console.log(error); // api call failed
});
// call backend server and return a promise of incoming data
function getJsonl() {
return $http({
url: 'urlNotShownForSecurity',
dataType: 'json',
method: 'GET',
data: { requestId: '123'},
headers: { 'Content-Type': 'application/json', requestId: '123'}
});
}
}
});

Related

Creating custom header for $http in AngularJs

In my controller i want send a request using get method if $http, in that get method i want to send the sessionID in headers. Below am giving the code snippet please check.
this.surveyList = function () {
//return session;
return $http.get('http://op.1pt.mobi/V3.0/api/Survey/Surveys', {headers: { 'sessionID': $scope.sessionid}})
.then(function(response){
return response.data;
}, function(error){
return error;
});
}
but this is not working when i send this vale in backend they getting null.
So how to resolve this.
we have a issue where the api is getting called twice from angular , however it works only once when called with the POSTMAN. And here with the custom header passed to the api, the action is called twice. What could be the reason for it?
Try in this way,
$http({
method: 'GET',
url: 'http://op.1pt.mobi/V3.0/api/Survey/Surveys',
headers: {
'sessionId': $scope.sessionid
}
}).then(function successCallback(response) {
// this callback will be called asynchronously
// when the response is available
}, function errorCallback(response) {
// called asynchronously if an error occurs,
// or server returns response with an error status.
});

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!

How does one chain successive/consecutive $http posts in angular?

I'm pretty new to AngularJS and am learning as I go along. How do I chain successive $http posts? I need reponse data from the first $http POST to use in the second $http POST, of which I'll also need the response which this second POST returns.
$http({
method: 'POST',
url: 'http://yoururl.com/api',
data: '{"field_1": "foo", "field_2": "bar"}',
headers: {'Content-Type': 'application/json'}
}).then(function(resp) {
$scope.data_needed = resp.data_needed;
// Can't possibly do another $http post here using the data I need, AND get its reponse?
// Would lead to a nested relationship, instead of adjacent chaining.
}, function(err) {
// Handle error here.
});
I've found out that it isn't an option to chain another $http post to the last line of code with another .then(function(resp) {});, for the same reason (referring to 1st comment in code block above).
Any advice? All I can seem to find are examples of chaining $http GETs, which do not involve getting and using a response. Cheers.
This is the way to go:
$http({...})
.then(
function success1(response) {
var data = response.data;
$scope.xxx = data.xxx;
return $http({...});
},
function error1(response) {
return $q.reject(response);
}
)
.then(
function success2(response) {
var data = response.data;
$scope.yyy = data.yyy;
},
function error2(response) {
// handle error
}
);
When a then() function returns a promise (the return $http(...) part), the chained then() gets called with the resolved value of the second promise. Also note the return $q.reject(...) part, necessary for the flow to proceed to the second error function, instead of the second success function.

Get Post Response in Service

i am trying to post my form data via service but if i am trying to get the response in console i am finding undefined can you suggest me what mistake i am committing,
i am new to angular so finding difficult to catch the issue.Here is my code
commonApp.service('CommonServices',function($http){
this.saveData=function(DataToInsert){
$http({
method :"POST",
data :DataToInsert,
url : 'myurl',
//headers :{'Content-Type': 'application/x-www-form-urlencoded'}
}).success(function(programApiResponse){
console.log(programApiResponse);
return programApiResponse;
}).error(function(programApiResponse){
return programApiResponse;
});
};
});
and my controller
$scope.makeprogram=function(){
//console.log($scope.programdata);
$scope.ProgInsResponse=CommonServices.saveData($scope.programdata);
console.log('1'+$scope.ProgInsResponse);
}
You aren't returning the promise at
this.saveData = function(DataToInsert){
$http({
...
This should probably be
this.saveData=function(DataToInsert){
return $http({
...
Then if you can add your own handlers
CommonServices.saveData($scope.programdata)
.then(...)
Last but not least if you have a half decent browser you can just log objects, don't log strings.
CommonServices.saveData($scope.programdata)
.then(function(){
console.log(arguments);
});
This is async nature issue. Try this
$scope.makeprogram=function(){
CommonServices.saveData($scope.programdata).then(function() {
console.log('1'+$scope.ProgInsResponse);
});
}
Since you are returning promise you need to wait before response comes.

Get response header in then() function of a ngResource object's $promise property after resource resolved?

I'm willing to retrieve the response header of a resource request, cause I've put pagination information and something else in it rather than the response body, to make the REST api clear.
Though we can get it from the success / error callback like below:
Object.get({type:'foo'}, function(value, responseHeaders){
var headers = responseHeaders();
});
Where 'Object' is my resource factory service.
Further, when I'm trying to make the route change after required resources resolved, I've tried this:
.when('/list', {
templateUrl: 'partials/list.html',
controller: 'ListCtrl',
// wait for the required promises to be resolved before controller is instantialized
resolve: {
objects: ['Object', '$route', function(Object, $route){
return Object.query($route.current.params).$promise;
}]
}
})
and in controller, just inject "objects" instead of Object service, because it's resolved and filled in with real data.
But I got problem when I try to get headers info from the "objects" in controller.
I tried objects.$promise.then(function(data, responseHeaders){}), but responseHeader was undefined.
How can I change the $resource service's behavior so that it throws the responseHeader getter into the $promise then() callback function?
My service "Object" for reference:
myServices.factory('Object', ['$resource',
function($resource){
return $resource('object/:id', {id: '#id'}, {
update: {method: 'PUT'},
});
}
]);
I had the exact same problem. I used an interceptor in the resource definition to inject the http headers in the resource.
$resource('/api/resource/:id', {
id: '#id'
}, {
index: {
method: 'GET',
isArray: true,
interceptor: {
response: function(response) {
response.resource.$httpHeaders = response.headers;
return response.resource;
}
}
}});
Then, in the then callback, the http headers are accesible through $httpHeaders:
promise.then(function(resource) {
resource.$httpHeaders('header-name');
});
I think I had a similar problem: After POSTing a new resource I needed to get the Location header of the response, since the Id of the new resource was set on the server and then returned via this header.
I solved this problem by introducing my own promise like this:
app.factory('Rating', ['$resource',
function ($resource) {
// Use the $resource service to declare a restful client -- restangular might be a better alternative
var Rating = $resource('http://localhost:8080/courserater/rest/ratings-cors/:id', {id: '#id'}, {
'update': { method: 'PUT'}
});
return Rating;
}]);
function RestController($scope, $q, Rating) {
var rating = new Rating();
var defer = $q.defer(); // introduce a promise that will be resolved in the success callback
rating.$save(function(data, headers){ // perform a POST
// The response of the POST contains the url of the newly created resource
var newId = headers('Location').split('/').pop();
defer.resolve(newId)
});
return defer.promise;
})
.then (function(newId) {
// Load the newly created resource
return Rating.get({id: newId}).$promise; // perform GET
})
.then(function(rating){
// update the newly created resource
rating.score = 55;
return rating.$update(); // perform PUT
});
}
We can't use .then for returning the header because the promise doesn't allow for multiple return values. (e.g., (res, err))
This was a requested feature, and was closed https://github.com/angular/angular.js/issues/11056
... the then "callbacks" can have only [one] argument. The reason for this is that those "callbacks" correspond to the return value / exception from synchronous programming and you can't return multiple results / throw multiple exceptions from a regular function.

Resources