I am loading an external JSON file with $.ajax(), and I am puzzled as to why my error function will only execute a console.log, or alert, but nothing else? In my example, if the JSON is found, the screen turns blue. If the JSON is not found (i.e. I change the name of the test.js file to something that doesn't exist), the screen should turn red, but this isn't happening. What's wrong with my code?
$.ajax({
url: 'test.js',
dataType: 'json',
timeout: 3000,
success: function( data ) { success() },
error: function( data ) { fail() }
});
function success(){
$("body").css("background", "blue"); //this works!
console.log("success"); //this works!
}
function fail(){
$("body").css("background", "red"); //this doesn't work :(
console.log("fail"); //this works!
}
Thanks,
If you were to write the above in pure js you'd need to specify almost the same parameters, just now you know specifically what happens and why it does or doesn't work because you can examine everything and it's not obscured by jQuery methods. note: the switch structure is my personal preference, most people do it with a (readyState === 4 && status === 200) but I always like to keep the ability to expand it to a more sophisticated error handling.
var xhr = new XMLHttpRequest();
xhr.responseType = "json";
xhr.timeout = 3000;
xhr.open("GET","test.js"); //method, url, async [default:true], username, password
xhr.onreadystatechange = function(){
if(xhr.readyState === xhr.DONE){
switch(xhr.status){
case:200
success(xhr);
break;
default:
failure(xhr);
break;
}
}
}
xhr.send();
function success(request){
document.body.style.background = "blue";
console.log(request.status,request.statusText); //> 200 "OK"
}
function failure(request){
document.body.style.background = "red";
console.log(request.status,request.statusText); // reason for error
}
since it's not a jQuery answer and therefore totally off topic I know I'm going to get a ton of downvotes, but I'm ok with that. I'll just have to answer a bunch of other questions to make up for the rep loss.
Related
I use Prototype.js to validate a form. For one of the fields, I have the prototype script ajax a request to a file. The file is a simple PHP file and will return '1' if the value is OK and '0' if the value is not OK. I have the script as below, which should work perfectly. The prototype validation is supposed to show a validation error message when a field does not pass validation, and not display / remove the message once the field passes validation. But in this case, even when the ajax file returns '1', the validation will display the error message anyway. Anyone able to help would be greatly appreciated!
['validate-number3', numessage3, function(v) {
new Ajax.Request('test.php?nr='+v, {
method:'get',
onSuccess: function(transport) {
var response = transport.responseText;
if(response == '1'){return true;}else{return false};
}
});
}],
the return value from Ajax.Request is the Ajax.Request object and returns as soon as the request is setup - the onsuccess callback is called after the request has been completed - so checking the results of Ajax.Request is not useful for what you want to accomplish.
The reason that this doesn't work as you expect, this is an asynchronous call which means it will start the call and then return control to the script while it is processing and then run the callbacks when it is completed.
Try it this way
new Ajax.Request('test.php?nr='+v, {
method:'get',
onSuccess: handleResponse
});
function handleResponse( transport ){
var response = transport.responseText;
if(response == '1'){
//everything is OK
}else{
//value is not OK
};
}
I was able to solve my question!
Thanks to this teriffic page: http://inchoo.net/ecommerce/magento/magento-frontend/magento-form-field-ajax-validation/ it was no problem. This is what I ended up with:
var ok = false;
new Ajax.Request('test.php?nr='+v, {
method:'get',
asynchronous: false,
onSuccess: function(transport) {
var response = transport.responseText;
if(response == '1'){ok = true;}else{ok = false;};
},
onComplete: function() {
if ($('advice-validate-number-pay_bank_no')) {
$('advice-validate-number-pay_bank_no').remove();
}
}
});
return ok;
function createLead(values) {
var url = "/api/v1/createlead/?apikey=XXXX-XXXX-XXXX-XXXX";
//debugger;
$.ajax({
type : "POST",
contentType : "application/x-www-form-urlencoded; charset=UTF-8",
url : url,
data : values,
success: function (result) {
result = $.parseJSON(result);
if (result.redirect) {
$(window).trigger('googleEvent' , 'regFailure');
window.location.href = values.returnUrl;
return;
}
else if (result.status === "OK" ) {
if (result.data.isPixelToBeFired){
$(window).trigger('googleEvent' , 'pixelFire');
}
else {
$(window).trigger('googleEvent', 'noPixelFire');
}
olp_sLeadId = result.data.leadId;
olp_sPathId = result.data.pathId;
$(window).trigger('googleEvent', 'regSuccess');
window.location = "path.html?curPathId=" + olp_sPathId
+ "&curLeadId=" + olp_sLeadId; // Enter the path
}
else {
// console.log('FAIL' , result , values);
$(window).trigger('googleEvent' , 'regFailue');
window.location.href = values.returnUrl;
return;
}
},
statusCode: {
404: function() {
$(window).trigger('googleEvent' , 'createLead404');
window.location.href = values.returnUrl;
//console.log('Something is seriously wrong');
return false;
}
},
failure: function (result) {
$(window).trigger('googleEvent' , 'createLeadFailure');
window.location.href = values.returnUrl;
//console.log('Something is seriously wrong');
return false;
}
});
}
I've been scratching my head here for a while, all version of IE seem to have an issue with this call. A few important pieces of information here:
values is a data object and I can verify that it has data.
All window .trigger functions are for Google analytics tracking, they are used in several other parts of the code and do not present an issue.
In IE the function seems to be spaced oddly, all the other functions line up properly, but this one seems to be aligned oddly, making me wonder if something isn't parsing right?
The success function appears to not run, and the failure and statusCode functions are completely ignored. This leads me to wonder if this isn't an issue with the jQuery methods, but they function elsewhere in the code?
I guess there is an issue with cache. The IE automatically cached the ajax request. To overcome this problem set option cache: false in you $.ajax code.
Example :
$.ajax({
type : "POST",
contentType : "application/x-www-form-urlencoded; charset=UTF-8",
url : url,
data : values,
cache : false,
// existing stuff
});
Hope this will help !!
Following up on my question from the other day, I've run into another thing that now I've spent too many hours banging my head against.
Mostly, I'm having trouble getting the SUCCESS form to submit. I tried this as well:
jQuery form submit
Here's the code in a semi-functional fiddle:
http://jsfiddle.net/ZcgqV/
Essentially what happens is this:
I bind a method to the form's submission via onSubmit (rather than click)
On submit, it calls a remote server via jQuery .ajax() call
If the response is "PENDING", retry every 1s, nine times
On failure, don't submit the form
On success, submit the form
No matter what I try, I can't get the form to either submit when I want it to without going into a loop, or not submit immediately while it tries the remote server.
~Frustrated-trying-100-things-that-fail-ly yours...
Here's the code directly in case you dislike fiddles:
var retries = 0;
var success = false;
var token = "toki wartooth is not a bumblebee";
$(document).ready(function() {
// Attach the action to the form
$('#tehForm').attr('onSubmit', 'onsubmit_action(event)');
});
function async(fn) {
setTimeout(fn, 1000);
}
function pollServer() {
$.ajax({
type: "POST",
cache: "false",
url: "/remoteCall",
dataType: "json",
data: {
ref_token: token
}
}).done(function(data, code, jqXHR) {
switch (data.status) {
case "SUCCESS":
alert("Success");
success = true;
// --> HERE IS WHERE I WANT THE FORM TO SUBMIT <--
break;
case "PENDING":
if (retries < 9) {
retries += 1;
async(function() {
pollServer();
});
} else {
alert("Failed after 9 tries");
}
break;
case "ERROR":
alert("Error");
break;
default:
alert("Some kind of horrible error occurred");
break;
}
}).fail(function(jqXHR, textStatus) {
var statusCode = jqXHR.status;
alert("Request failed: " + statusCode + " " + textStatus);
});
}
function onsubmit_action(event) {
pollServer();
if (success === false) {
// RETURN FALSE DIDN'T WORK, SO I FOUND THIS
event.preventDefault();
}
}
EDIT:
Again, the real problem here is that I stop submission of the form. On SUCCESS, I want the form to submit. Currently if I use .submit() in SUCCESS, the AJAX is called again, starting the process over. What I want is the ACTION of the FORM to fire on SUCCESS only.
Trying to use as much of the original code as possible; here is a solution:
Post form with post back
http://jsfiddle.net/tpm7v/4/
Post form via Ajax
http://jsfiddle.net/tpm7v/5/
var retries = 0,
token = "toki wartooth is not a bumblebee",
sendRequest,
handelResponse,
postFormToServer,
$theForm = $('#tehForm');
$(document).ready(function() {
// Attach the action to the form
$theForm.bind('submit', onsubmit_action);
});
sendRequest = function() {
$.ajax({
type: "POST",
cache: "false",
url: "/remoteCall",
dataType: "json",
data: {
ref_token: token
},
success: handelResponse
});
};
postFormToServer = function() {
$.ajax({
type: "POST",
cache: "false",
url: "/remoteCallToTakFormData",
dataType: "json",
data: $form.serialize(),
success: function() {
alert('success!');
}
});
};
handelResponse = function(data, code, jqXHR) {
switch (data.status) {
case "SUCCESS":
postFormToServer();
break;
case "PENDING":
if (retries < 9) {
retries += 1;
setTimeout(sendRequest , 1000);
} else {
alert("Failed after 9 tries");
}
break;
case "ERROR":
alert("Error");
break;
default:
alert("Some kind of horrible error occurred");
break;
}
};
function onsubmit_action(evt) {
evt.preventDefault();
sendRequest();
}
Keep in mind I am going off the code your provided. You should be able to port this to work with your actual implementation. You may also want to try something like https://github.com/webadvanced/takeCommand to help clean up all the Ajax calls.
Please see my comment above for more information, but I think the problem you're seeing here is this:
Every time pollServer() fires, it's not only doing another ajax call, but it's prepping to do 9 possible ajax calls every second based on the retries loop. Since you're then setting another pollServer() call with the async() method, you're basically compounding your ajax calls out of control. You want to get the ajax call out of your retry loop, then you should at least be only getting 1 request a second, not 1, then 2, then 3, etc. I may have read the code wrong, but this is my best guess on what you're seeing.
UPDATE: I'm not sure my explanation was clear, so I thought I'd add some additional info. Basically, every time pollServer() is called and gets a PENDING response, it calls async, which registers a setTimeout(). setTimeout() keeps running every second, doing pollServer(), which then calls asynch, which registers another setTimeout() which also runs every second. Now you have two functions, which each then call setTimeout(), assuming they're still getting PENDING as a response from the server. So after 2 rounds of failed calls, you have 4 setTimeout() calls each firing an ajax call (and a new setTimeout) every second.
First off it should be: $('#tehForm').submit(onsubmit_action); or $('#tehForm').on("submit",onsubmit_action); or something like that. Never use the string form to pass a function. It uses the evil eval statement.
Next, after POST the data is already submitted. That is the whole reason for post. Why do you need all sorts of error handling in the done section. Fail should handle error handling.
If you are asking about how to try again after a timeout, try this:
Is it possible to check timeout on jQuery.post()?
I believe timeout will fall into fail.
So try this:
var retries = 0,
max_tries = 9,
success = false,
token = "toki wartooth is not a bumblebee";
$(document).ready(function() {
// Attach the action to the form
$('#tehForm').on("submit",submit_the_form);
});
function submit_the_form(e){
var dfd = $.ajax({
url : "sendTokenPolling",
data : {"token":token},
timeout : 5000 //you may want 1000, but I really think that is too short
});
dfd.done(function(){
//success, form posted
});
dfd.fail(function(){
//did not work/timedout
if (retries < max_tries){
retries += 1;
submit_the_form(e);
}
});
}
var = msg
$.get('json-signup-erros.php',{},function(data){msg=data},'json');
function focushint()
{
alert (msg) // this works
}
$("input").focus(focus);
alert(msg) //this doesnot work
can anyone tall me way??
You are making an AJAX request which is asynchronous.
msg will contain the value only after the request has been made.
You should put the code that uses msg into the Ajax request's success callback (the function(data)).
(There is the theoretical possibility to make the request synchronous using async: false but that is not good practice and should be used only if it's unavoidable.)
I agree with Pekka - you need to consider something like this:
var = msg;
$.get('json-signup-erros.php',{}, function(data, response)
{
if(response == "success")
{
msg = data;
alert(msg);
}
else
{
alert("Whoops something went wrong, please try again.");
}
},'json');
function focushint()
{
alert (msg); // this works
}
$("input").focus(focushint);
NB. I put a "success" check in the $.get... I see this all the time - you should not assume that your Ajax Http Request is going to return a 200 response! i.e. if no data get's returned due to an error (404, 500, 401) you can't alert it and you may want to warn the user that something went wrong by adding an else clause.
var = msg;
$.get('json-signup-erros.php',{}, function(data, response)
{
if(response == "success")
{
msg = data;
alert(msg);
}
else
{
alert("Whoops something went wrong, please try again.");
}
},'json');
function focushint()
{
alert (msg); // this works
}
$("input").focus(focushint);
alert(msg); // this is still does not work
If you want to access the msg outside a jQuery function like focushin that will be in the same scope
I'm recently fooling around with some ajax polling techniques. However, it seems like I can't overwrite the onreadystatechange handler from a XMLHttpRequest object in FireFox (3.6.7).
On tracking the problem why FF throws an exception when trying to access onreadystatechange, I realized it depends whether the send() method was called or not.
In other words, here is an example (plain js, no jQuery so far), that works:
(This is fairly simplified just for a demonstration)
var myxhr = new XMLHttpRequest();
myxhr.open("GET", "/my/index.php");
myxhr.onreadystatechange = function(){
console.log('ready state changed');
};
console.log("onreadystatechange function: ", myxhr.onreadystatechange);
myxhr.send(null);
This works, better said it's possible to access myxhr.onreadystatechange here. If I switch the last two lines of code, FF throws an exception, basically telling me that I'm not allowed to access this object.
myxhr.send(null);
console.log("onreadystatechange function: ", myxhr.onreadystatechange);
Fails.
So where is my actual problem?
Well, I want to use jQuery's $.ajax(). But if I try to overwrite the onreadystatechange method of a XHR object that was returned from $.ajax(), I receive the same FireFox exception.
Ok I already found out why this happens, so I thought about, hey what about the beforeSend property of $.ajax() ? So I basically tried this:
var myxhr = $.ajax({
url: "/my/index.php",
type: "GET",
dataType: "text",
data: {
foo: "1"
},
beforeSend: function(xhr){
var readystatehook = xhr.onreadystatechange;
xhr.onreadystatechange = function(){
readystatehook.apply(this, []);
console.log('fired');
};
},
success: function(data){
console.log(data);
},
error: function(xhr, textStatus, error){
console.log(xhr.statusText, textStatus, error);
}
});
Guess what, FireFox throws an exception. So what do you do now? You digg into the jQuery source, like I did. But that brought more questions than answers actually. It looks like beforeSend() is really called before xhr.send() is executed. So I'm wondering why on earth FireFox does not allow to overwrite the handler at this point.
Conclusion?
It's impossible to create a custom readystatechange handler with jQuery/Firefox ?
I agree with Maz here, you can still benefit form the query handling and creating of the object, and also no need to patch jquery for this
however, if you dont mind patching jquery you could add these lines
// The readystate 2
} else if ( !requestDone && xhr && xhr.readyState === 2 && isTimeout !== 'timeout' && s.state2) {
s.state2.call( s.context, data, status, xhr );
// The readystate 3
} else if ( !requestDone && xhr && xhr.readyState === 3 && isTimeout !== 'timeout' && s.state3) {
s.state3.call( s.context, data, status, xhr );
before this line: (jQuery v 1.4.4) or just search for the readyState === 4 in the source
// The transfer is complete and the data is available, or the request timed out
} else if ( !requestDone && xhr && (xhr.readyState === 4 || isTimeout === "timeout") ) {
now you can use the $.ajax again and put a handler up for state2 and state3 like so:
$.ajax({
url: 'http://www.stackoverflow.com',
cache: false,
success:function(){console.log('success');},
error: function (){console.log('error');},
complete: function (){console.log('complete');},
state2: function (context,data,status,xhr) {console.log('state2');},
state3: function (context,data,status,xhr) {console.log('state3');}
});
it doesnt exactly behave like the other handlers, eg returngin false wont do a thing
but you can still handle the xhr object and abort that way
ill see if i can submit this to be included in the source later this day, who knows they might accept it
If you want a large level of customization, you can just get the XMLHttpRequest object and control it yourself.
var x=new $.ajaxSettings.xhr();
x.onreadystatechange=function(){ ... }
...
You can do this by doing something like that:
$.ajax({
type: "POST",
url: "Test.ashx",
data: { "command": "test" },
contentType: "application/x-www-form-urlencoded; charset=utf-8",
dataType: "json",
beforeSend: function (request, settings) {
$(request).bind("readystatechange", function (e) { alert("changed " + e.target.readyState); });
}});