jQuery .load doesn't work whilst ajax query is in progress - javascript

I have a web application that loads different content into the same div (.content) using either an ajax request or a .load() request.
A simplified version of the ajax request is:
$(document).on('click', '.button1', function() {
$.ajax({
type: "POST",
url: "/path/to/file/ajax.php",
data: {
'param1': 'xyz',
'param2': '123',
},
timeout: 10000,
dataType: "json",
success: function(data) {
if (data.status == 'Success') {
$('.content').html(data.result);
} else if (data.status == 'Error'){
console.log('Something went wrong')
}
},
error: function(x, status, error) {
if (status === "timeout") {
console.log('Request Timed Out');
}
},
});
});
on another button I have:
$(document).on('click', '.button2', function() {
$('.content').load('/path/to/file/getContent.php?ref=foo');
});
The problem is that if I click on button1, and then click on button 2 whilst the ajax request is still executing, nothing happens. (ie. getContent.php doesn't seem to return anything for anywhere between 15-30 seconds)
Clicking on button 2 returns the results instantly, but as soon as button1 is clicked and the ajax request is being processed, it seems to "stall" the entire web app until it's completed (or errors).
(I've also tried using the abort() method to cancel the ajax request, but the same problem persists, even when the abort is successful).
UPDATE
See solution/Answer below

Following on from the tip from #adeneo, I did some more research into session_start and ajax calls which led me to this article:
http://konrness.com/php5/how-to-prevent-blocking-php-requests/
The problem absolutely was to do with session_start locking the session file which causes back-end issues with multiple ajax requests. Following the advice in the article above, I made use of session_write_close() in my PHP and everything is working great.
If it helps anyone else, I actually changed my code from session_start() to:
if (session_status() == PHP_SESSION_NONE) {
session_start();
session_write_close();
}
This makes session variables readable, but no longer locks the session file causing ajax request delays. (It also checks to make sure session_start() hasn't already been called)

Related

Using ajax long polling to update a response on my page from an external API

I have the following ajax long polling script
(function poll(){
$.ajax({ url: "<?php echo URL::to('/internal/v1/checkTxn'); ?>", success: function(data){
//Update your dashboard gauge
console.log(data.status); //Data is getting logged
if(data.status == 'success'){ //This condition is not being checked
console.log('suucesful'); //Not coming
}
}, dataType: "json", complete: poll, timeout: 1000 });
})();
The backend PHP code is as follows
if(isset($_POST['status']) && $_POST['status']){
$data = ['status'=>$_POST['status']];
$json = json_encode( $data );
echo $json;
}
Flow
When I render the page, the ajax script runs and waits for response. When I checked the network tab, ajax was endlessly making requests to the URL specified.
I get a form post from an external website to the backend PHP which I need to push to the jquery.
But when a post is happening, nothing is being logged in the console. But if I hard code some values in the $json and echo it, its coming up in the console.
I am facing two issues
When a post happens on the PHP script, its not coming up in the ajax code.
When I hard code (simulated the response posted by the external form post) the $json and echo it, its coming up in the console, but the condition for data.status== 'success' is not getting checked.
What is wrong in this. Am I missing something?
UPDATE
I could fix the "condition not being checked" as there was something wrong the json being echoed.
Now to avoid confusion, the flow for this
User open the page,
> The ajax starts the long polling process to my PHP code, waiting for a
> response.User enters payment details in a form which is my html,clicks on pay, a pop up appears
> which renders the banks login page (Payment gateway).After user entering all
> details in the pop up (banks page), bank sents a server to server call about the status of
> transaction to my notificationURL
> ('mydomain.com/internal.v1/checkTxn'). As soon as I get a POST on this
> URL(I will close the pop up), my ajax polling should get the data posted to my PHP and there by
> I will show the status of TXN to the user on the same card form he entered his details earlier and
> the pop window closes. The response here is returned by my PHP code to the ajax.
The
> post coming to my PHP code is a server to server post which is posted
> by a Payment Gateway.
1. let's debug this:
set your ajax error call back,
$(function(){
(function poll(){
$.ajax({ url: "http://tinyissue.localhost.com/test.php", success: function(data){
//Update your dashboard gauge
console.log(data.status); //Data is getting logged
if(data.status == 'success'){ //This condition is not being checked
console.log('suucesful'); //Not coming
}
},error:function(err){
console.info('error fired...');
console.info(err);
}, dataType: "json", complete: poll, timeout: 1000 });
})();
});
run this, you will get console
error fired...
Object {readyState: 4, responseText: "", status: 200, statusText: "OK"}
2. Why went to error callback:
Why ajax response status is 200 and statusText is "OK" , error callback still fired instead of success?
Your AJAX request contains the following setting:
dataType: "json"
The documentation states that jQuery:
Evaluates the response as JSON and returns a JavaScript object. (...)
The JSON data is parsed in a strict manner; any malformed JSON is
rejected and a parse error is thrown.
This means that if server returns invalid JSON with a 200 OK status then jQuery fires the error function and set the textStatus parameter to "parsererror".
Solution: make sure that the server returns valid JSON. It is worth noting that an empty response is also considered invalid JSON; you could return {} or null for example which validate as JSON.
3. Why ajax return invalid JSON:
In your mind, at server side, you checked the $_POST['status'] to make sure last call success in the loop poll, only $_POST['status'] is set, you will echo json, or it echo nothing.
But, unfortunately, at the beginning of the call loop, the first time the ajax called, you didn't set status to post. Then it echo nothing, then it went error callback, also went complete callback, then call again without status to post. See, it went a bad cycle.
4. Solution:
Set a status value to post at the first ajax call.
$(function(){
(function poll(){
var status = 'success';
$.ajax({ url: "http://tinyissue.localhost.com/test.php", success: function(data){
//Update your dashboard gauge
console.log(data.status); //Data is getting logged
status = data.status;
if(data.status == 'success'){ //This condition is not being checked
console.log('suucesful'); //Not coming
}
},error:function(err){
console.info('error fired...');
console.info(err);
status = 'error';
}, type:'post',dataType: "json", data:{status:status}, complete: poll, timeout: 1000 });
})();
});
If you are using long polling, you could have a cache issue.
First, when your post comes to your system, check that checkTxn changes.
Last, you can add a random parameter (by adding date in millis, for example) in url query, you will not use it, but your server will think your requests are different.
Please, check it and let us know.
#Edit: Sure #Ajeesh, I'll explain it:
(function poll(){
$.ajax({ url: "<?php echo URL::to('/internal/v1/checkTxn'); ?>?_ts=" + new Date().getTime(), success: function(data){
//Update your dashboard gauge
console.log(data.status); //Data is getting logged
if(data.status == 'success'){ //This condition is not being checked
console.log('suucesful'); //Not coming
}
}, dataType: "json", complete: poll, timeout: 1000 });
})();
By doing this, cache will not be used, because all queries are different for your server/browser.
On the other hand, I ask you for any changes in your page when you receive the POST, so, if not, your ajax will never receive the notification, do you know what I mean?

jQuery Synchronous Form Submission with Timeout

I am attempting to submit a form to an external site which is prepared to receive it, but there were some points when the external site was done and caused my site to be stuck waiting with no response just using form.submit()
I wrote the following to try to handle this, but the timeout is not being thrown.
$.ajax({
async: false,
url: url,
data: $('#tppForm').serialize(),
type: 'POST',
timeout: 5000,
statusCode: {
404: function() {
console.log('Site Not Found');
},
500: function() {
console.log('Site Down');
}
},
error: function() {
console.log('Timeout');
}
});
I checked both the jQuery documentation as well as other sources, the behavior of timeout: is not clearly specified for async:false.
My suggestion is to change this to async:true to better handle the unpredictable nature of remote (network) calls. See jquery ajax() async false and jQuery ajax success anonymous function scope .
This will change the challenge to one where your client side (browser) must have a "ready" state flag that can indicate to the user they should wait and block overlapping calls. Personally I like to alter the submit button text / color for user feedback. Just prior to making your AJAX call you should also check the state flag to ensure there are no pending operations.

$.post is not working (anywhere)! Why?

My calls to $.post are not working all over my code. I'm not sending the request to other domains and, actually, I'm doing everything localhosted. My localhost alias was automatically defined by the Mac OS X 10.8 as ramon.local and I'm requesting from http://ramon.local/linkebuy_0.7/resourceX to http://ramon.local/linkebuy_0.7/resourceY. There are no errors on Chrome's console.
The server side doesn't receive the request and I can check it by accessing directly from the browser (typing the URL).
It's not just one call that is not working, none of them are. They were all working days ago and I'm suspicious that I accidentally changed something on my local settings. What could it be?
Here's an example of what I'm facing:
$.post(
<<CORRECT URL INSIDE THE DOMAIN>>,
{},
function(response) {
console.log('THIS SHOULD BE PRINTED ON CONSOLE');
alert('THIS SHOULD BE POPPED UP');
}
);
I don't get the alert, neither the console message while running the code above. So I tried the following:
$.support.cors = true;
$.ajax({
url: "http://ramon.local/linkebuy_0.7",
dataType: "json",
type: "GET",
crossDomain: true,
success: function (data) {
console.log(data);
},
error: function (xhr, status, error) {
alert(error + " - " + status);
}
});
I just came with $.support.cors = true; and crossDomain: true to check if it was a cross domain issue. So I was alerted No Transport - error same way as before.
What can I do to solve that?
Thanks in advance.
Try this and see if you are getting any alert:
// Assign handlers immediately after making the request,
// and remember the jqxhr object for this request
var jqxhr = $.post("your url", function() {
alert("success");
}).success(function() {
alert("second success");
}).error(function() {
alert("error");
}).complete(function() {
alert("complete");
});
// perform other work here ...
// Set another completion function for the request above
jqxhr.complete(function() {
alert("second complete");
});​
Well, I solved the problem in a very strange way.
I deleted the JQuery file and downloaded it again, replacing the old one. Happens it worked out.
So, if you're:
Making AJAX requests that are not cross-domain;
Using JQuery for it (e.g. $.post, $.get, etc);
Getting No Transport AJAX error
Then re-download and replace you're JQuery source.
Else, if you're making cross-domain requests (not this case), then look for JSONP and try to set $.support.cors = true; at the beginning of you're code.
Thanks everyone for the comments and answers.

Salesforce - success handler for $.ajax call

I have a form that I have been submitting to Salesforce with standard form submit action. By default, you can tell Salesforce to redirect you to a given URL after the POST has completed.
I no longer wish to be redirected since I have other activities on the form page. No problem, my page is already using jQuery so I can use the handy $.ajax utility like this:
$('#wrapper').on('click', '#formsubmit', function(e) {
e.preventDefault();
var formData = $('#subForm').serialize();
$.ajax({
type: "POST",
url: "https://www.salesforce.com/servlet/servlet.WebToLead?encoding=UTF-8",
data: formData,
success: function() {
console.log('success!'); // or not!
},
error:function (xhr, ajaxOptions, thrownError){
console.log(xhr.status); // 0
console.log(thrownError); // empty
}
});
});
In my misguided brain, I imagined that Salesforce would return my good ol' redirect, which would count as a "success" that I can just discard/ignore. Misguided indeed!
I can see a 200 OK result (which usually means "success") but the success callback isn't tripped.
The lead is added to the Salesforce database
Inspecting the content of what's returned shows zero; there is no content in the response.
The error callback IS being tripped (despite the 200 OK) but maybe due to intentionally not redirecting it is seen as a "resource not available"? (therefore my status code is 0, and there is no content in the thrownError?).
Any advice on identifying this as a successful POST so that I can trigger additional actions in a callback? I don't want to TOTALLY ignore the response, or I could end up in a scenario in which I'm acting on a failed POST as if it was successful. I need to capture the success somehow.
It occurred to me that it could be a cross-site scripting issue as well, but since the application doesn't exchange data in JSONP, I'm not sure how to get around that (and I'm not sure how to identify it in the first place).
Few things here:
1) The redirect response being sent by salesforce's API is most likely being interpreted as an error code.
2) The response code of the subsequent page (after the redirect) is 200 OK, from the sound of it.
3) It is not possible to do a POST request using JSONP. This is a limitation of JSONP; which is not actually an AJAX request, but an HTTP GET request wrapped inside of a dynamically generated script tag. Also, JSONP only works if the request yields an HTTP response of 200 OK.
I would recommend using your own server-side intermediary to handle your AJAX POST request. This will act as a proxy between your front-end app and salesforce's API. This will also allow you to better control the response being sent to your app.
var formData = $('#subForm').serialize();
var response = $.ajax({
type: "POST",
url: "https://www.salesforce.com/servlet/servlet.WebToLead?encoding=UTF-8",
data: formData,
success: function() {
console.log('success!'); // or not!
},
error:function (xhr, ajaxOptions, thrownError){
console.log(xhr.status); // 0
console.log(thrownError); // empty
}
}).responseText;
where var response will contain the return value from your ajax call

jQuery.get queue the request until network connection available

I am using jQuery Mobile to create a webapp to look at and update a CRM type system.
The mobile app sends update using jQuery.get and jQuery.post and they work fine when network connection is available.
How should I code or what can I use to queue the jQuery.get and jQuery.post calls when the network connection is not available so they are sent when it becomes available again.
Edit: ah poo, i just noticed you said 'jQuery Mobile', I initially read that as jquery for mobile lol. Ummm, this'll probably only work as long as jQM supports ajax the same as normal jquery
I had an idea with a secondary ajax request, but you shouldn't need that. Just set up your AJAX like this, and give it a timeout. If it takes > 4 (should be enough for a broadband connection, but some phones may need ~10-15) seconds for the server to respond, it'll just try the ajax request again up to retryLimit, which can be set, then changed later as well after the 50 times is up (i.e. should it send when the program is idle and has no data perhaps?). When it connects, it'll go to the success function, which will then send the data to the server.
So it'd be like:
$.ajax({
type: 'GET',
timeout: 4000,
tryCount : 0,
retryLimit: 50,
success:function(data) {
sendSavedData();
}
error: function(xhr, textStatus, errorThrown) {
if(textStatus == 'timeout') {
this.tryCount++;
if(this.tryCount <= this.retryLimit) {
$.ajax(this);
return;
}
var check = confirm('We have tried ' + this.retryLimit + ' times to do this and the server has not responded. Do you want to try again?');
if(check) {
this.timeout = 200000;
$.ajax(this);
return;
} else {
return;
}
}
}
});

Categories

Resources