AngularJS $http ajax request is not asynchronous and causes page to hang - angularjs

I have a service where I am pulling data from server. When I click the button to send out the request to server through this service, the window freezes until I receive a response from server. Is there anything I can do to make this request asynchronous ?
Here is my service.
app.factory('service', function($http) {
return {
getLogData : function(startTime,endTime){
return $http({
url: baseURL + 'getLogData',
method: 'GET',
async: true,
cache: false,
headers: {'Accept': 'application/json', 'Pragma': 'no-cache'},
params: {'startTime': startTime , 'endTime': endTime}
});
}
};
)};
HTML.
<button ng-click="getData()">Refresh</button>
<img src="pending.gif" ng-show="dataPending" />
Code
$scope.getData = function(){
service.getLogData().success(function(data){
//process data
}).error(function(e){
//show error message
});
}

While there is some argument about the pros and cons of your approach, I am thinking that the problem is answered here: AJAX call freezes browser for a bit while it gets response and executes success
To test if this in fact part of the problem, dummy up a response and serve it statically. I use Fiddler or WireShark to get the response and then save to a file like testService.json. XHR and all of it's various derivatives like $HTTP $.ajax see it as a service though the headers might be slightly different.

Use the success promise, and wrap up the log data in a set of objects that you can attach to a $scope.
So instead of having your service have a blocking method, have it maintain a list of "LogEntries".
// constructor function
var LogEntry = function() {
/*...*/
}
var logEntries = [];
// Non-blocking fetch log data
var getLogData = function() {
return $http({
url : baseURL + 'getLogData',
method : 'GET',
async : true,
cache : false,
headers : { 'Accept' : 'application/json' , 'Pragma':'no-cache'},
params : {'startTime' : startTime , 'endTime' : endTime}
}).success(function(data) {;
// for each log entry in data, populate logEntries
// push(new LogEntry( stuff from data ))...
};
}
Then in your controller, inject your service and reference this service's log data array so Angular will watch it and change the view correctly
$scope.logEntries = mySvc.logEntries;
Then in the HTML, simply do something over logEntries:
<p ng-repeat="logEntry in logEntries">
{{logEntry}}
</p>

use this code to config
$httpProvider.useApplyAsync(true);

var url = //Your URL;
var config = {
async:true
};
var promise= $http.get(url, config);
promise.then(
function (result)
{
return result.data;
},
function (error)
{
return error;
}
);

Related

AngularJS access $http on onNotification event PushNotification cordova plugin

I'm using the plugin https://github.com/phonegap-build/PushPlugin/ with Angular 1.3 and I need to send the regid to server when receive "registered" event.
The problem is that I don't have $http object to call my server on this context. How can I achieve that, please?
function onNotification(e){
if(e.event == "registered"){
var req = {
method: "POST",
url: "http://myurl.com/?var="+e.regid
};
$http(req).success(function(data){
alert(data);
});
}
}
I just learned how to inject $http into the event method:
$http = angular.injector(["ng"]).get("$http");
Change $http call as follows, .success is deprecated.
$http({
method: "POST",
url: "http://myurl.com/?var="+e.regid
}).then(function successCallback(response) {
// this callback will be called asynchronously
// when the response is available
alert(response);
}, function errorCallback(response) {
// called asynchronously if an error occurs
// or server returns response with an error status.
});
Ref. : https://docs.angularjs.org/api/ng/service/$http
Regards.

ExpressJS IP and AngularJS $http get

I'm trying to learn ExpressJS and I'm having trouble getting IP address from an Express route to display in the browser via Angular controller.
I'm using 2 Nodejs modules (request-ip and geoip2) to get the IP and then lookup geolocation data for that IP. Then trying to use Angular to display the geolocation data in the browser using an Angular $http get call.
My Express route for the IP:
// get IP address
router.get('/ip', function (req, res, next) {
console.log('requestIP is ' + ip);
// geolocation
geoip2.lookupSimple(ip, function(error, result) {
if (error) {
//return res.status(400).json({error: 'Something happened'});//default
return res.sendStatus(400).json({error: 'Something happened'});
}
else if (result) {
return res.send(result);
}
});
});
And my AngularJS controller code:
function MainController($http) {
var vm = this;
vm.message = 'Hello World';
vm.location = '';
vm.getLocation = function() {
$http({
method: 'GET',
url: 'localhost:8000/ip'
}).then(function (result) {
console.log(result);
return vm.location = result;
});
};
};
The Hello World message displays but not the location...? I can also go to localhost:8000/ip and see the JSON result. The result doesn't appear in Chrome's console either. The result is a json object like this:
{"country":"US","continent":"NA","postal":"98296","city":"Snohomish","location":{"accuracy_radius":20,"latitude":47.8519,"longitude":-122.0921,"metro_code":819,"time_zone":"America/Los_Angeles"},"subdivision":"WA"}
I'm not sure why the Hello Word displays and the location doesn't when it seems that I have everything configured correctly... so obviously I'm doing something wrong that I don't see...?
You have initialised 'vm.location' as a string when in fact it is a JSON object.
vm.location = {};
You need to adjust the url paramater in your request to:
url: '/ip'
As you are sending back JSON from Express.js, you should change your response line to:
return res.json(result);
Do you call vm.getLocation() somewhere in your code after this?
The data you need is under result.data from the response object.
Also in order to display the data in the html you have to specify which property to display from the vm.location object (vm.location.country, vm.location.city etc..).
From angular docs about $http:
The response object has these properties:
data – {string|Object} – The response body transformed with the transform functions.
status – {number} – HTTP status code of the response.
headers – {function([headerName])} – Header getter function.
config – {Object} – The configuration object that was used to generate the request.
statusText – {string} – HTTP status text of the response.
Is this express js and angular hosted on the same port? If so please replace your
$http({
method: 'GET',
url: 'localhost:8000/ip'
}).then(function (result) {
console.log(result);
return vm.location = result;
});
with
$http({
method: 'GET',
url: '/ip'
}).then(function (result) {
console.log(result);
return vm.location = result;
});
It may be considered as CORS call and you have it probably disabled.
You can also specify second function to then (look code below) and see if error callback is called.
$http({
method: 'GET',
url: '/ip'
}).then(function (result) {
console.log(result);
return vm.location = result;
}, function (error) {
console.log(error);
});

Refresh <DIV> after submit data Angular JS

I want to show the total direct sales without reloading with angular js,
when I was still using the reload when processing cart
JS
.controller('CartCtrl',function($scope,$http,$ionicPopup,$timeout,$location){
$scope.plusCart = function() {
$http({
method : 'POST',
url : 'http://192.168.1.33/so-ku/www/server/menu/plus_cart',
headers : { 'Content-Type' : 'application/json' },
data : JSON.stringify({ rowid: $scope.currentItem.rowid, qty : $scope.currentItem.qty })
}).success(function(data) {
console.log(data);
total_cart();
location.reload(true);
});
}
function total_cart() {
$http.get('http://192.168.1.33/so-ku/www/server/menu/total_cart').
then(function(response){
$scope.total = response.data.records;
});
}
HTML
<div ng-controller="CartCtrl">
<div ng-repeat="x in total" style="padding-top: 10px;" ng-init="total_cart()">
Rp {{x.total}}
</div>
</div>
I want result div with total is automatically calculated when i submit post
If your total_cart() function works, then just remove the line with location.reload(true) and it should refresh the data.
To chain two $http operations, first be sure the subsequent function returns the promise from the $http call:
function total_cart_promise() {
var url = 'http://192.168.1.33/so-ku/www/server/menu/total_cart';
//save promise
var promise = $http.get(url)
.then(function(response){
$scope.total = response.data.records;
});
//return promise for chaining
return promise;
};
Then in the first function, use the .then method and return the subsequent promise to the first XHR success handler:
$scope.plusCart = function() {
$http({
method : 'POST',
url : 'http://192.168.1.33/so-ku/www/server/menu/plus_cart',
//headers : { 'Content-Type' : 'application/json' },
//data : JSON.stringify({ rowid: $scope.currentItem.rowid, qty : $scope.currentItem.qty })
data : { rowid: $scope.currentItem.rowid,
qty : $scope.currentItem.qty }
//}).success(function(data) {
//USE .then method
}).then(function successHandler(response) {
console.log(response.data);
//total_cart();
//return promise to chain subsequent XHR
return total_cart_promise();
//location.reload(true);
});
}
By chaining to subsequent XHR GET methods, there is no need to reload the page.
Because calling the .then method of a promise returns a new derived promise, it is easily possible to create a chain of promises. It is possible to create chains of any length and since a promise can be resolved with another promise (which will defer its resolution further), it is possible to pause/defer resolution of the promises at any point in the chain. This makes it possible to implement powerful APIs. --AngularJS $q Service API Reference - Chaining Promises
Also note that there is no need to stringify the data, the AngularJS framework uses Content-Type: application/json by default and the framework automatically does JSON.stringify.

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.
});

Example of progress on file upload in AngularJS $http POST

I am trying to get a 'progress' event from AngularJS $http POST request for file upload.
After looking at $http upload file progress in AngularJS, I came across one recent angular.js git commit, that suppose to resolve the issue Add XHR progress event handling to $http and $httpBackend.
Did anyone achieve this working? And if so, can kindly show the example?
PS. I'd prefer to stay with $http rather than create my own XMLHttpRequest. The reason is that my backend expects to get json object combined with multipart file data. And the attempt to make through XMLHttpRequest is failing with error message that backend doesn't see the json object part of request "Required String parameter 'objData' is not present. The request sent by the client was syntactically incorrect." While in the POST message I see "Content-Disposition: form-data; name="objData"" in Firebug.
$scope.uploadFile = function() {
var url = buildUrl('/upload');
var data = {objData: $scope.data, fileData: $scope.file};
var formData = new FormData();
formData.append("objData", angular.toJson(data.objData));
formData.append("fileData", data.fileData);
var xhr = new window.XMLHttpRequest();
xhr.upload.addEventListener("progress", uploadProgress, false);
xhr.open("POST", url);
xhr.setRequestHeader("Content-Type","application/json;charset=utf-8");
xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
xhr.send(formData);
};
At time of writing $http doesn't support the notify method of the new 1.2 $q. So you have to use jquery xhr. Its rather simple once set up:
Notice that we return a promise so your consumer of uploadFile would do uploadFile(..).then(success, fail, progress)
$scope.uploadFile = function() {
var deferred = $q.defer();
var getProgressListener = function(deferred) {
return function(event) {
//do some magic
deferred.notify(magic);
};
};
var formData = new FormData();
formData.append("objData", angular.toJson(data.objData));
formData.append("fileData", data.fileData);
$.ajax({
type: 'POST',
url: buildUrl('/upload'),
data: formData,
cache: false,
// Force this to be read from FormData
contentType: false,
processData: false,
success: function(response, textStatus, jqXHR) {
deferred.resolve(response);
},
error: function(jqXHR, textStatus, errorThrown) {
deferred.reject(errorThrown);
},
xhr: function() {
var myXhr = $.ajaxSettings.xhr();
if (myXhr.upload) {
myXhr.upload.addEventListener(
'progress', getProgressListener(deferred), false);
} else {
$log.log('Upload progress is not supported.');
}
return myXhr;
}
});
return deferred.promise;
};

Resources