response.responseText adds previous responseText (node.js, prototype) - ajax

This is my node.js function that uses res.write:
function: ping(){
res.write(JSON.stringify({"datatype":"ping"}));
setTimeout(ping, 30000);
}
This is the client, request written in prototype:
this.pushconnection = new Ajax.Request(pushserveraddress, {
method: 'get',
evalJSON: 'false',
onInteractive: this.pushconnectionInteractive.bind(this)
});
}
pushconnectionInteractive: function(response) {
}
The problem is that response.responseText will grow with every res.write that comes through.
Example:
1st ping() received: response.responseText = {"datatype":"ping"}
2nd ping() received: response.responseText = {"datatype":"ping"}{"datatype":"ping"}
3rd ping() received: response.responseText = {"datatype":"ping"}{"datatype":"ping"}{"datatype":"ping"}
I'm not sure if node.js is re-sending the data, or if prototype is storing the data. What I need to do is have response.responseText = the last data sent without using res.end();

You're probably calling this.pushconnection more than once.
If you instantiate this.pushconnection as it's own Ajax Object and continue to use the same ajax object then your response will grow.
Try this instead:
this.pushconnection = function (pushserveraddress) {
return new Ajax.Request(pushserveraddress, {
method: 'get',
evalJSON: 'false',
onInteractive: this.pushconnectionInteractive.bind(this)
});
}
Then you can call this by saying:
var ajax = this.pushconnection("example.com");

every response add to previous one, to get last object sent if u use that php function :
(1st add headers)
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');
header('connection: keep-alive');
(2 send data)
function send_message($data_array) {
echo json_encode($data_array).PHP_EOL;
ob_flush();
flush();
}
in your js (Prototype): to get last response
new Ajax.Request(sUrl, {
onInteractive:function(xhr){
var lastString = xhr.responseText.split("\n");
var lastObjectSent = lastString[lastString.length-2].evalJSON();
if(lastObjectSent.bValid){
if(parseInt(lastObjectSent.bValid,10) === 1){
this.status="finished";
loadPage('done.php');
}else{
setNotification(oResult.sText,"Failure",5000);
}
}else if(lastObjectSent.progress){
$('duplicatePassDates').down('.bar').setStyle('width:'+lastObjectSent.progress+'px');
}
},
onSuccess:function(xhr){
if(this.status!=="finished"){
this.onInteractive(xhr);
}
},

Related

Ajax request with CORS redirect fails in IE11

I'm trying to make an ajax request to a resource on the same domain. Under certain circumstances the request gets redirected(303) to an external resource. The external resource supports CORS.
In browsers like Chrome, Firefox or Safari the request succeeds.
In IE11 the request fails with error:
SCRIPT 7002: XMLHttpRequest: Network Error 0x4c7, The operation was canceled by the user
The ajax request is made with jQuery:
$.ajax({
url: "/data",
type: "POST",
dataType: "json",
contentType: "application/json;charset=UTF-8",
data: JSON.stringify({name: 'John Doe'})
}).done(function () {
console.log('succeeded');
}).fail(function () {
console.log('failed');
});
I've build a little example which demonstrates the problem. You could see the code here.
w/o redirect
w/ redirect
Is there a way to solve this problem? What am I missing?
In the initial definition of the CORS-standard, redirects after a successful CORS-preflight request were not allowed.
IE11 implements this (now outdated) standard.
Since August 2016, this has changed, and all major browsers now support it (Here's the actual pull request).
I'm afraid to support <=IE11 you'll have to modify your server-side code as well to not issue a redirect (at least for <=IE11).
Part 1) Server-side (I'm using node.js express here):
function _isIE (request) {
let userAgent = request.headers['user-agent']
return userAgent.indexOf("MSIE ") > 0 || userAgent.indexOf("Trident/") > 0
}
router.post('data', function (request, response) {
if (_isIE(request)) {
// perform action
res.set('Content-Type', 'text/plain')
return res.status(200).send(`${redirectionTarget}`)
} else {
// perform action
response.redirect(redirectionTarget)
}
})
Part 2 Client-side
Note: This is pure Javascript, but you can easily adapt it to your jQuery/ajax implementation.
var isInternetExplorer = (function () {
var ua = window.navigator.userAgent
return ua.indexOf("MSIE ") > 0 || ua.indexOf("Trident/") > 0
})()
function requestResource (link, successFn, forcedRedirect) {
var http
if (window.XMLHttpRequest) {
http = new XMLHttpRequest()
} else if (window.XDomainRequest) {
http = new XDomainRequest()
} else {
http = new ActiveXObject("Microsoft.XMLHTTP")
}
http.onreadystatechange = function () {
var OK = 200
if (http.readyState === XMLHttpRequest.DONE) {
if (http.status === OK && successFn) {
if (isInternetExplorer && !forcedRedirect) {
return requestResource(http.responseText, successFn, true)
} else {
successFn(http.responseText)
}
}
}
}
http.onerror = http.ontimeout = function () {
console.error('An error occured requesting '+link+' (code: '+http.status+'): '+http.responseText)
}
http.open('GET', link)
http.send(null)
}
its already answered - have a look - https://blogs.msdn.microsoft.com/webdev/2013/10/28/sending-a-cors-request-in-ie/

AngularJS: Prevent calling multiple $http request to get same data

I still don't understand how the Promise API works. I want to know if there's a way to get a data whenever I need it without calling multiple HTTP request. Here's an exemple :
Session Service :
All it does is either get the session object (which contains datas) or get session ID which returns a number.
app.factory('sessionFactory', ['$resource', 'requestFactory',
function ($resource, requestFactory) {
var oSession = {};
var session = {
/**
* Get session ID
* #return {Number}
*/
sessionID: function () {
if (typeof oSession.id !== "undefined") {
return oSession.id;
} else {
return requestFactory.getObject('/application/current_session').then(function (response) {
oSession = response;
return oSession.id;
});
}
},
/**
* Get session object (GET)
* #return {Object} data in JSON format
*/
getCurrentSession: function () {
if (!oSession.id) {
return requestFactory.getObject('/application/current_session').then(function (response) {
oSession = response;
return oSession;
});
}
}
};
return session;
}]);
Request HTTP Service :
This service only does HTTP request.
app.factory('requestFactory', ['$http', '$q', '$timeout',
function ($http, $q, $timeout) {
return {
getObject: function (jsonURL, params) {
// $q service object
var deferred = $q.defer();
// regular ajax request
$http({
method: 'GET',
url: jsonURL,
params: params
})
.success(function (result, status, headers, config) {
// promise resolve
deferred.resolve(result);
})
.error(function (result, status, headers, config) {
// called asynchronously if an error occurs
// or server returns response with an error status.
deferred.reject('Erreur request : ' + status);
});
return deferred.promise;
}
};
}]);
So to get my Session Object, I do sessionFactory.getCurrentSession with callback function(then...) and it works perfect. Later on, I only need to get the session ID so I would do sessionFactory.sessionID, but it works only if I add the callback function (then...), why is that? I thought my global JavaScript object oSession already has data since the first HTTP request.
I want to prevent doing a spaghetti code and keep the code as clean as possible, with a more object approach. Is it possible?
It looks like you're trying to do too much with the promise API. It's already built into the $http service so you shouldn't need to invoke it yourself. Try this instead:
app.factory('requestFactory', ['$http',
function ($http) {
return {
getObject: function (jsonURL, params) {
// regular ajax request
return $http({
method: 'GET',
url: jsonURL,
params: params
})
.success(function (result, status, headers, config) {
return result;
})
.error(function (result, status, headers, config) {
// called asynchronously if an error occurs
// or server returns response with an error status.
throw new Error('Erreur request : ' + status);
});
}
};
}]);
By returning the result of the $http call, you are in fact returning a promise. You can then chain additional resolution code onto the return value. See the "Chaining Promises" section of the $q documentation.
IF you want to cache your previous http response so that it will not make an http call again
you can use angular-cached-resource
bower install angular-cached-resource
angular.module('myApp',['ngCachedResource'])
instead of $resource use $cachedResource, it will cache the network call to local storage, every time you make a call it will resolve immediately even though it makes a call to backend and updated the cache.
you can also use angular-cache it will cache all your http get calls you can set timeout as well exclude url in its configuration
bower install angular-cache

Wait for node.js callback to be completed before ending AJAX request

I am using jQuery on the front to make an AJAX post request using $.post(). I also pass a success function which will do something with the data returned. On my node.js server, I am using express to handle requests, the post request calls another function passing a callback which in the callback does a res.send(). How can I get the request not to finish until the callback is done?
My client-side code is:
$.post("/newgroup/", {name: newgroupname}, function(data) {
console.log(data); // Returns undefined because requests ends before res.send
});
My server-side code is:
app.post('/newgroup/', function(req, res){
insertDocument({name:req.body.name, photos:[]}, db.groups, function(doc){
res.send(doc);
});
});
The insertDocument function is:
function insertDocument(doc, targetCollection, callback) {
var cursor = targetCollection.find( {}, {_id: 1}).sort({_id: -1}).limit(1);
cursor.toArray(function(err, docs){
if (docs == false){
var seq = 1;
}
else {
var seq = docs[0]._id + 1;
}
doc._id = seq;
targetCollection.insert(doc);
callback(doc);
});
}
If the code you've shown us is the real code then the only possibility is that the thing you are returning doc is actually undefined. The callback on the client will not fire before res.send() is triggered.
Are you sure that the callback in insertDocument is exactly as you think? Often callbacks are of the form function(err,doc), i.e. try this:
app.post('/newgroup/', function(req, res){
insertDocument({name:req.body.name, photos:[]}, db.groups, function(err, doc){
res.send(doc);
});
});
Okay I found the answer, I am not sure why this works, I just had to change the name of the variable I was sending to the callback, I assume this is because it had the same name as a parameter, so I changed my insertDocument function to look like this
function insertDocument(doc, targetCollection, callback) {
var cursor = targetCollection.find( {}, {_id: 1}).sort({_id: -1}).limit(1);
cursor.toArray(function(err, docs){
if (docs == false){
var seq = 1;
}
else {
var seq = docs[0]._id + 1;
}
doc._id = seq;
targetCollection.insert(doc);
var new_document = doc;
callback(new_document);
});
}
Could it be a sync/async issue? I don't know what library you are using for your saves, but is it a case were the call should be something more like this?
targetCollection.insert(doc, function(err, saveddoc) {
if (err) console.log(err);
callback(saveddoc);
});

Doing ajax call on response of another function but not working

I have registration form and i have created three function in jquery
First one is validate the form.
Second one is for checking the email uniqueness with ajax request.
Third one is for creating user this also with ajax request.
My flow on submit event is that first i am calling validation function and then on the response of that function i calling the function to check the email uniqueness on the response of this a an ajax request is done to create a user.
First one is validate the form.
function validateregForm()
{
if($('#u_name').val()=="" || !IsEmail($('#u_email').val()) || $('#u_pwd').val().length<6 || $('#c_pwd').val()!=$('#u_pwd').val())
{
if($('#u_name').val()=="")
{
$('#reg_error1').show();
}
if(!IsEmail($('#u_email').val()))
{
$('#email_msg').remove();
$('#reg_error2').show();
}
if($('#u_pwd').val().length<6)
{
$('#reg_error3').show();
}
if($('#u_pwd').val()!=$('#c_pwd').val())
{
$('#reg_error4').show();
}
return false;
}
else
{
return true ;
}
Second one is for checking the email uniqueness with ajax request.
function chkmail(email) {
var posting=$.post('http://localhost/tv100.info/index.php/user/chkmail',{u_email:$('#u_email').val()});
posting.done(function(data){
if(data=='success')
{
$('#email_error').css('display','none');
$('#email_msg').css('display','block');
return true;
}
if(data=='failure')
{
$('#email_msg').css('display','none');
$('#email_error').css('display','block');
return false;
}
});
}
Third one is for creating user this also with ajax request.
$('#regform').submit(function(event) {
var res=validateregForm()
event.preventDefault();
if(res)
{
var email=chkmail();
}
if(email)
{
$('#loading2').show();
var posting=$.post('http://localhost/tv100.info/index.php/user/create_user',$("#regform").serialize());
posting.done(function(data)
{
$('#loading2').hide();
if(data=="success")
{
$('#reg_panel').append('<span id="reg_msg">Registration successful Now You are logged IN</span>');
$('#overlay').fadeOut(300);
$('#login').html('Logout');
$('#sign_in').hide();
$('#cmmnt_field').show();
}
if(data=="failure")
{
$('#reg_panel').append('<span id="res_msg">Something Went Wrong try again Latter</span>');
}
});
}
});
Just telling the case
if(res)
{
var email=chkmail(); // for getting the result in var email, ajax will wait until the success
}
if(email) // In your case before completing the ajax request, javascript come to this line and won't return true. So it it always go to else part.
You can do the user creation on success of chkmail success part. It will work fine
Error in your first line of validateregForm() function,
change
if($('#u_name').val=="" || !IsEmail($('#u_email').val())
to
if($('#u_name').val() =="" || !IsEmail($('#u_email').val())
^ `.val()` here.
You need to learn about asynchronously and synchronously concepts. Ajax calls are usually Asynchronously. Simple set the paramter async as false of each ajax request and you will get the result. From documentation
async (default: true)
Type: Boolean
By default, all requests are sent asynchronously (i.e. this is set to true by default).
If you need synchronous requests, set this option to false.
Cross-domain requests and dataType: "jsonp" requests do not support synchronous operation.
Note that synchronous requests may temporarily lock the browser, disabling any actions while the request is active.
As of jQuery 1.8, the use of async: false with jqXHR ($.Deferred) is deprecated; you must use the success/error/complete callback options instead of the corresponding methods of the jqXHR object such as jqXHR.done() or the deprecated jqXHR.success().
You need to use a callback to process the result of email validation
function chkmail(email, callback) {
var posting = $.post('http://localhost/tv100.info/index.php/user/chkmail', {
u_email : email
});
posting.done(function(data) {
if (data == 'success') {
callback(true);
} else if (data == 'failure') {
callback(false);
}
});
}
$('#regform').submit(function(event) {
var res = validateregForm()
event.preventDefault();
if (res) {
chkmail($('#u_email').val(), function(valid) {
if (valid) {
$('#email_error').css('display', 'none');
$('#email_msg').css('display', 'block');
$('#loading2').show();
var posting = $.post('http://localhost/tv100.info/index.php/user/create_user', $("#regform").serialize());
posting.done(function(data) {
$('#loading2').hide();
if (data == "success") {
$('#reg_panel').append('<span id="reg_msg">Registration successful Now You are logged IN</span>');
$('#overlay').fadeOut(300);
$('#login').html('Logout');
$('#sign_in').hide();
$('#cmmnt_field').show();
}
if (data == "failure") {
$('#reg_panel').append('<span id="res_msg">Something Went Wrong try again Latter</span>');
}
});
} else {
$('#email_msg').css('display', 'none');
$('#email_error').css('display', 'block');
}
});
}
});

prototype javascript ajax request runs back end perl script but continues to return 500

Newbie to this - This code is works - in that the call to the script does what it is supposed to but returns the condition 500 and I can not see why. I am looking for any suggestions or changes that I should be making to make this work.
Thanks to all who respond.
function get_update_odometer(vehicle_key,odometer_value){
var url = "[%Catalyst.uri_for('/invoice/dispatch_util/get_update_odometer')%]";
new Ajax.Request(url, {
method: 'get',
parameters: {
key: vehicle_key,
ovalue: odometer_value
},
asynchronous:false,
onSuccess: successFunc,
onFailure: failureFunc
});
var return_v = $('rcontainer').innerHTML;
document.getElementById('odometer').value = return_v;
return true;
}
function successFunc(response){
if (200 == response.status){
var container = $('rcontainer');
var content = response.responseText;
container.update(content);
}
}
function failureFunc(response){
alert("Call has failed " + response.status );
}
Error code is coming from server side, and you provided the client part.
So have a look if your server script get_update_odometer is working, is callable by your web server and etc ...

Resources