I am submitting a form via ajax (using JQuery) and the time taken for the response to be received can be anything from a few seconds to a few minutes. This is expected and cannot be changed. This is working fine in all browsers except the stock Android browser which is timing out my request after 120 seconds, no matter what I set the timeout to in the ajax constructor. Is there a way around this?
The code for the Ajax request is quite simple:
var jqxhr = $.ajax({
type: 'post',
timeout: 500000,
url: 'process.php',
data: $('form').serialize(),
success: function (data) {
alert("success" + data);
},
error: function(xhr, error){
alert("Error: " + error + ", XHR status: " + xhr.status);
},
});
When submitted on Android with a script that takes over 120 seconds, the error handler is hit with the following message:
Error: error, XHR status: 0
Please have a look at this article indicating that the error may arise from the presence of a HTTP Expires header.
Use a tool like Fiddler to monitor the HTTP network traffic and present the results for further analysis.
You have a syntax error.
var jqxhr = $.ajax({
type: 'post',
timeout: 500000,
url: 'process.php',
data: $('form').serialize(),
success: function (data) {
alert("success" + data"); <------- HERE
},
error: function(xhr, error){
alert("Error: " + error + ", XHR status: " + xhr.status);
},
});
Try your code with this on-line JavaScript runner but remove the extra double qoute.
var jqxhr = $.ajax({
type: 'post',
timeout: 500000,
url: 'process.php',
data: $('form').serialize(),
success: function (data) {
alert("success" + data);
},
error: function(xhr, error){
alert("Error: " + error + ", XHR status: " + xhr.status);
},
});
After some research it appears that others have had similar issues with AJAX timeouts at ~60ms and ~120ms. Those seem like very deliberate values (like internal browser settings), and I am going to go ahead and assume from the lack of responses/solutions that we can't get around those timeouts.
Have you considered posting your AJAX request to a separate server/service which does not do any processing and can return a quick 200 OK response. Then let this second server handle the communication with the slow server. I know this sucks, but it might be your only solution (and might result in a snappier app and happier users).
Can you give any more insight into your app? Is this a PhoneGap app or is the app hosted at some domain that you can access from the browser? Are you able to provide a URL?
Have you seen the below thread.
AJAX (XmlHttpRequest) timeout length by browser
Regards,
SP
Try inserting your code on a separate blank html page with nothing but your ajax request, jquery attached and some basic alerts like success, status code or errors etc. Put the correct file path in url handler, in data handler, put some static values like name:"Macros",site:"stackoverflow". When all gets ready, you should get alert message on desktop browser, if its success, try running that html page on stock android browser. If that works as well.. The problem might be jquery conflict with some other script or your $("form#testform").serialize() function.
How about if you retry after the timeout?
$("form#testform").submit(function(){
var allFormValues = $("form#testform").serialize();
$.ajax({
cache:false,
timeout:8000, // I chose 8 secs for kicks
tryCount : 0,
retryLimit : 5,
type:"POST",
url:"someurl.php",
data:allFormValues,
error:function(xhr, status, error) {
if (status == 'timeout') {
this.tryCount++;
if (this.tryCount <= this.retryLimit) {
alert("Timeout! Retrying now!");
//try again
$.ajax(this);
return;
}
return;
} else {
// not a timeout? not a problem
alert("Error: " + status + ", XHR status: " + xhr.status);
}
},
success:function(response){
alert(response);
}
});
});
Related
I am working on HTML5 mobile app using jQuery mobile.
This is my code:
$(document).on("click","#send_mobile_number",function(){
var mobile = $('#mobile_number').val();
var user_id = sessionStorage.getItem("user_id");
$('.ui-loader').show();
$.ajax({
url: BASE_URL+'users/send_sms_code.php',
type: 'POST',
datatype: 'json',
data: "user_id="+user_id+"&mobile="+mobile+"&type=1",
async:false,
success: function (response) {
var data = jQuery.parseJSON(response);
$('.ui-loader').hide();
if(data.status == 'Fail') {
$('.very_mob_no_message').html('Sorry some error occurred,try again.');
}else{
$('#close_mob_popup').trigger('click');
setTimeout(function()
{
$('.click_mobile_verify').trigger('click');
}, 500);
$('#send_mobile_verify_span').hide();
$('#after_mobile_send_span').show();
$('#moble_number_div').hide();
$('#user_code_div').show();
$('#user_code').val(data.sms_code);
//alert(window.localStorage.getItem('mobile'));
//sessionStorage.setItem("mobile",mobile);
window.localStorage.setItem("mobile",mobile); // IT IS NOT WORKING
$('.very_mobile_message').html('Enter code which is <br/> sent to your mobile number.');
}
},
error: function (jqXHR, textStatus, errorThrown) {
//alert(jqXHR.status);
}
});
});
I want to store mobile number in session using window.localStorage.setItem("mobile",mobile);. It is working when I run on my browser but when I runt on mobile phone as APP it stop working. Why this happening. I am checking android phone.
Just use localStorage.mobile = "mobile". It's as simple as that. localStorage is a global object and can be accessed and manipulated as any other object. The only difference with regular objects is that it can store only strings.
You can then retrieve your value using alert( localStorage.mobile ); // will alert "mobile"
So finally found the solution, I need to set webSettings.setDomStorageEnabled(true); on android code and after this localstorage is working perfectlly.
I encountered a problem when I try to package my sencha-touch app using phonegap. Everything works fine except accessing WFS in phonegap. (And the app has no problem running in browser, WFS access is OK)
My phonegap version is 2.9; openlayer version is 2.13
Here I present my simple code. You can also check the example codes in the following site: http://openlayers.org/dev/examples/wfs-filter.html
var rootUrl = window.location.protocol + "//" + window.location.host + '/';
var map;
function init() {
map = new OpenLayers.Map({
div: "map",
layers: [
new OpenLayers.Layer.WMS(
"Natural Earth",
"http://demo.opengeo.org/geoserver/wms",
{ layers: "topp:naturalearth" }
),
new OpenLayers.Layer.Vector("WFS", {
strategies: [new OpenLayers.Strategy.BBOX()],
protocol: new OpenLayers.Protocol.WFS({
url: rootUrl + 'proxy.py?url=http://demo.opengeo.org/geoserver/wfs',
featureType: "tasmania_roads",
featureNS: "http://www.openplans.org/topp"
}),
styleMap: new OpenLayers.StyleMap({
strokeWidth: 3,
strokeColor: "#333333"
}),
})
],
center: new OpenLayers.LonLat(146.7, -41.8),
zoom: 6
});
}
In phonegap there's no problem accessing WMS, but when I try WFS, it never work.
Comparing to the link I showed you before, there's a road displayed in the map, and it is obtained through WFS. In my phonegap app, the road will not be displayed.
I'm wondering whether it is a WFS issue, or phonegap issue. Something is blocking my access to WFS in my phonegap app.
Please give me some suggestions and hints, guys! I will really appreciate it.
function getLayerList() {
$.ajax({ url: rootUrl + 'proxy.py?url=http://192.168.0.23/LBEService/Service1.svc/GetEventList',
//async: false,
data: JSON.stringify({}),
type: "POST",
dataType: "json",
contentType: "application/json; charset=utf-8",
success: function (result) {
console.log(result);
$("#demo").html(result[0].event_NAME);
},
error: function (xhr, ajaxOptions, thrownError) {
alert(xhr.status);
alert(thrownError);
}
}).done(function () {
});
}
Have you added the domain that is hosting the WFS to the white list?
http://docs.phonegap.com/en/1.9.0/guide_whitelist_index.md.html
On android PhoneGap window.location.protocol is 'file:' and window.location.hostname is "", so your app will probably be looking for file://proxy.py? which doesn't exist on your device.
To solve this issue I test the protocol, and set up OpenLayers.Proxy accordingly, thus:
if( location.protocol == 'file:' ) {
OpenLayers.ProxyHost = "";
} else {
OpenLayers.ProxyHost = "/cgi-bin/proxy.cgi?url=";
}
So in your case, if protocol is 'file:', I think you need to drop 'proxy.py?'
Tip: debug your android app using Chrome on your PC (chrome://inspect/#devices) and you'll see the request that android is making.
I'm developping a mobile application, which should connect to a web server. The application is written with jQM and simply imported in an android web view. I tried to solve this problem using the jStorage plugin, but it seems that it's impossible to share the local storage between the different pages. So I tried to implement this, but it does not work and continues sending null.
Here are my code samples:
Javascript:
function getToken(authCode) {
var jsonUrl = mainUrl + "/auth/authorizeToken?grant_type=authorization_code&client_id=bc89fb879a64eb8e422b94d5c39&client_secret=b5c2974b78f7f3f7aee2bed182&redirect_uri=redirection&code="+authCode;
$.ajax({
url: jsonUrl,
type: "GET",
dataType: "jsonp",
success: function(data) {
localStorage.setItem( "access_token", data.access_token);
localStorage.setItem( "refresh_token", data.refresh_token);
localStorage.setItem( "logged", "true");
}
});
}
function valTokens() {
access_token = localStorage.getItem("access_token");
refresh_token = localStorage.getItem("refresh_token");
}
After that the values are set to null. The .java files are the same as in the sample from the link given.
I'm using PhoneGap to build an Android app. Using either jQuery or Zepto, I'm able to make calls to the website APIs using the $.ajax call. However, when the website returns a 401 (unauthorized) response, there seems to be no callback from the ajax call - none of "success", "error", or "complete" get called.
Note that the same code works fine when the response is 200 or 500.
I'm using Zepto 1.0rc1 and/or jQuery 1.7.2 with PhoneGap 1.6.1 .
function make_base_auth(user, password) {
var tok = user + ':' + password;
var hash = btoa(tok);
return "Basic " + hash;
}
$('#button').on('touchstart', function() {
console.log("UPLOAD --- ");
$.ajax({
url: 'https://mywebsite/api/v1.0/test/?ts=' + new Date().getTime(),
type: 'GET',
beforeSend: function (xhr){
xhr.setRequestHeader('Authorization', make_base_auth('username', 'password'));
},
success: function(data, status, xhr) {
console.log("AJAX: SUCCESS: " + data);
$('h1').text("AJAX!!");
},
error: function(xhr, errortype, error) {
console.log("AJAX: FAIL: " + errortype + " - " + error);
$('h1').text("AJAX FAIL");
},
complete: function() {
console.log("--- Complete");
}
});
return false;
});
I just had the same problem. When I get HTTP 401 back and use
$.ajax({
...
timeout: 5000, // Some timeout value that makes sense
...
});
then the error callback is called with {"readyState":0,"status":0,"statusText":"timeout"}. In that case you would have to guess that the real error is the HTTP 401.
Alternatively you can use
$.ajax({
...
async: false, // :-(
...
});
and your error callback will get something like {"readyState":4,"responseText":"<html>...</html>","status":401,"statusText":"Unauthorized"} back.
Downgrade phonegap. Yes. You read that right.
I tried 1.4.1: didn't work.
I tried 1.3.0: works.
So yeah, that's that.
I am using $getJSON to hit a node.js endpoint under Phonegap and Android. The code looks like this
$.getJSON(
serverURL + "/login?callback=?",
"playerId=" + playerId + "&pwd=" + pwd,
function(data){
theCallbackFunction.call(null, JSON.parse(data));
},
function(jqXHR, textStatus, errorThrown) {
alert('error ' + textStatus + " " + errorThrown);
}
);
In response to the login request, my server sends back a session cookie. This cookie is only accepted and returned in subsequent AJAX requests if 'Third-Party Cookies' are enabled in the browser. I have found that older Android devices (e.g. 2.2) allow this by default but new ones (3.2) do not.
Is it possible to force Phonegap to enable Third-Party Cookies for my Android application?
I had a similar problem when trying to authenticate with my server. I instead resorted to the use of localStorage. See the code below or here.
var store = window.localStorage,
request = {
url: {SERVER_URL},
headers : {
Cookie: store.getItem('session')
},
complete: function (jqXHR, status){
if (status != 'success') {
console.log('ajax status: failure');
} else if (store.getItem('session') != null) {
console.log('ajax status: session exists');
} else {
console.log('ajax status: saving cookie');
var header = jqXHR.getAllResponseHeaders();
var match = header.match(/(Set-Cookie|set-cookie): (.+?);/);
if (match) {
session = match[2];
store.setItem("session", session);
}
}
}
}
$.ajax(request);
In the above, I'm checking for the localStorage variable 'session' and if it exists, it will send the stored cookie. If it doesn't exist, it will take the 'set-cookie' paramater sent in the headers by the server, match the pertinent part and store it in the 'session' variable of localStorage.
Phonegap does not support cookie abstraction. Never really needed to as there are already apps/plug-ins that do. Plus it is intended to wrap up the functionality of the phone/device, not the browser. You CAN however do this with a jQuery plug-in.
https://github.com/carhartl/jquery-cookie