I have an Ajax Call to an API which will return correctly (200) when the URL and the parameters are fine. Now I am trying to force an error with a bad request. Console will inform me about error code 400 but never seems to get into the error method. Instead it gets stuck in some jquery line and never returns.
fetch: function(successCallback, errorCallback) {
var apiUrl = this.applyFilter(filters);
var self = this;
this.log('fetch', apiUrl, currentSearchMode);
$.ajax({
url: apiUrl,
type: 'GET',
cache: (debug) ? true: false,
processData: true,
crossDomain: true,
scriptCharset: 'UTF-8',
jsonp: 'callback',
dataType: 'jsonp',
success: function(data, statusText, jqXHR) {
console.log(jqXHR);
// if(jqXHR.status == 400){
// console.log('there is an error');
// }
self.log('fetch::success', data);
if (typeof data.error !== 'undefined') {
showNoResultError = true;
var appData = lastValidResult[currentSearchMode];
} else {
showNoResultError = false;
var appData = self.normalize[currentSearchMode](self, data);
lastValidResult[currentSearchMode] = appData;
}
if (typeof successCallback === 'function')
successCallback(appData);
},
error: function(jqXHR, textStatus, errorThrown) {
//do sth here
// if(jqXHR.status&&jqXHR.status==400){
// alert(jqXHR.responseText);
// }else{
// alert("Something went wrong");
// }
// console.log('works now');
// self.log('fetch::error', textStatus, errorThrown);
// if (typeof errorCallback === 'function')
// errorCallback.apply(this, arguments);
},
complete: function(jqXHR, textStatus) {
console.log(jqXHR);
console.log('complete');
}
});
},
So the image shows where it gets stuck. I can only catch complete and success functions but when there a 400 response there is nothing happening. Tried anything, also done(), fail() since I assumed there might be a problem with deprecated behavior. But same problem there. Can anybody help, please?
Try:
fetch: function(successCallback, errorCallback) {
var apiUrl = this.applyFilter(filters);
var self = this;
this.log('fetch', apiUrl, currentSearchMode);
$.ajax({
url: apiUrl,
type: 'GET',
cache: (debug) ? true: false,
processData: true,
crossDomain: true,
scriptCharset: 'UTF-8',
jsonp: 'callback',
dataType: 'jsonp',
success: function(data, statusText, jqXHR) {
console.log(jqXHR);
// if(jqXHR.status == 400){
// console.log('there is an error');
// }
self.log('fetch::success', data);
if (typeof data.error !== 'undefined') {
showNoResultError = true;
var appData = lastValidResult[currentSearchMode];
} else {
showNoResultError = false;
var appData = self.normalize[currentSearchMode](self, data);
lastValidResult[currentSearchMode] = appData;
}
if (typeof successCallback === 'function')
successCallback(appData);
},
error: function(data){
console.log(data);
console.log(data.responseText);
},
complete: function(jqXHR, textStatus) {
console.log(jqXHR);
console.log('complete');
}
});
},
then, show me what's in your console
Error callback will not be fired for crossdomain requests or for jsonp requests.
search for the below in the reference link.
Note: This handler is not called for cross-domain script and cross-domain JSONP requests.
Reference: http://api.jquery.com/jquery.ajax/
You can look at this answer for how to handle errors for jsonp requests
JSONP request error handling
Related
I have the following javascript:
function foo()
{
var someObject = $("#someTextbox").val();
var contentType = 'application/x-www-form-urlencoded; charset=UTF-8;';
AjaxRequest(someObject, 'html', 'post', '/ErrorCheck/SaveToFile', contentType, function(response)
{
//stuff
}, function(error)
{ });
}
function AjaxRequest(data, dataType, type, url, contentType, success, error, args)
{
try
{
var useFD = false;
var form = new FormData();
if (type.toUpperCase() == 'POST')
{
if (contentType && contentType.indexOf('application/x-www-form-urlencoded; charset=UTF-8;') === 0)
{
form.append("MyData", JSON.stringify(data));
url = antiForgeryToken.add(url);
useFD = true;
}
}
$.ajax(
{
processData: useFD ? false : true,
mimeType: useFD ? "multipart/form-data" : "",
async: args.async,
cache: args.cache ? true : false,
data: useFD ? form : data,
dataType: dataType,
type: type,
url: url,
contentType: contentType,
traditional: true,
headers:
{
'__RequestVerificationToken': antiForgeryToken.token() != false ? antiForgeryToken.token().val() : '',
'__loginUserId': $('#hidLOGINUSERID').val()
},
beforeSend: function(request)
{ },
success: function(data, textStatus, XMLHttpRequest)
{
try
{
success(data, textStatus, XMLHttpRequest);
}
catch (e)
{}
},
error: function(XMLHttpRequest, textStatus, errorThrown) {},
complete: function(XMLHttpRequest) {}
});
}
catch (err)
{}
}
In the above scenario, useFD is true.
Then in my ErrorCheck controller's SaveToFile method, I have the following:
public void SaveToFile()
{
try
{
if (Request.Form.Count > 0)
{
//do stuff
}
}
catch (Exception ex)
{
ElmahLogUtility.ErrorException(ex);
}
}
However, Request.Form.Count is always zero. I got this solution from a question I asked a few months ago here. I accepted the solution there back in October and I know this code was working, however it didn't get to a testing environment until just recently and it is no longer working, not even in my local environment.
What am I doing incorrectly?
i am writing this code in my html page to hide one id in that page..alerts are also not working..method is not called
*<script>
alert("yo");
$(function checkUsertype(email_id)
{
alert("yup")
var usertype = $("#txtusertype").val();
$.ajax({
alert("hide")
url: 'rest/search/userType?email_id='+email_id,
type : "GET",
datatype : 'json',
cache : false,
success : function(data)
{
if(usertype=='webuser')
{
$("#themer").hide();
}
},
error : function(xhr, data, statusText,errorThrown)
{
}
});
})
alert("yo");
<script/>*
This is the problem.
$.ajax({
alert("hide")
You're trying to alert inside the ajax which is Syntax error. Try removing the alert inside ajax and it should work.
You can use alert in success, error callbacks as follow:
$(function checkUsertype(email_id) {
var usertype = $("#txtusertype").val();
$.ajax({
url: 'rest/search/userType?email_id=' + email_id,
type: "GET",
datatype: 'json',
cache: false,
success: function(data) {
alert('In Success'); // Use it here
console.log(data); // Log the response
if (usertype == 'webuser') {
$("#themer").hide();
}
},
error: function(xhr, data, statusText, errorThrown) {
alert('In Error'); // Use it here
console.log(errorThrown); // Log the error
}
});
});
I have a javascript function like this :
addGas = function(options){
var working = false;
$(document).ajaxSend(function(event, jqxhr, settings) {
if (settings.url == '/add_gas') {
working = true;
}
});
if(working) {
return;
}
$.ajax({
url: options.url,
data: options,
type: "POST",
success: function(data, textStatus, jqXHR){
$(".btn").addClass("added").text(" Added gas ").prepend("<i></i>");
},
error: function(jqXHR, textStatus, errorThrown){
}
});
}
So the way I test this is that I put 10 seconds sleep in my controller, and try to click the button again, and it makes a post request who is waiting, because my server can server one request at a time.
But I wanted not to send a post request if one is already running, alternatively alert a message if the request is already running.
How can I do that?
Create a singleton handling its own state, this way you dont pollute the rest of the code with unused variables
gasHandlerBuilder = function(){
var ajaxInProgress = false;
return {
add_gas: function(options){
if(ajaxInProgress){ return; };
ajaxInProgress = true;
$.ajax({
url: options.url,
data: options,
type: "POST",
success: function(data, textStatus, jqXHR){
ajaxInProgress = false;
$(".btn").addClass("added").text(" Added gas ").prepend("<i></i>");
},
error: function(jqXHR, textStatus, errorThrown){
ajaxInProgress = false;
}
});
}
}
}
var gasHandler = gasHandlerBuilder();
gasHandler.add_gas(options);
You should use some flag, something like this :
var recieved = false;
$.ajax({
url: "http://first.call/",
})
.done(function( data ) {
// Do something with that data and enable the flag
recieved = true;
});
addGas = function(options){
var working = false;
$(document).ajaxSend(function(event, jqxhr, settings) {
if (settings.url == '/add_gas') {
working = true;
}
});
if(!recieved) {
return;
}
$.ajax({
url: options.url,
data: options,
type: "POST",
success: function(data, textStatus, jqXHR){
$(".btn").addClass("added").text(" Added gas ").prepend("<i></i>");
},
error: function(jqXHR, textStatus, errorThrown){
}
});
}
In an application I want to use jQuery deferred to implement our Ajax success and error handling on a central place. Everything works great if I put strings in the data option, but if I want to put an array in the data option, it sends this as a string!
My deferred implementation:
Application = {
ajax: function(options) {
var deferred = $.Deferred(function (d) {
var defaults = {
cache: false,
type: 'post',
traditional: true,
dataType: 'json'
},
settings = $.extend({}, defaults, options);
d.done(settings.success);
d.fail(settings.error);
d.done(settings.complete);
var jqXHRSettings = $.extend({}, settings, {
success: function (response, textStatus, jqXHR) {
/*
JSON Reponse
{
status: 'error' or 'success',
code: 200, (HTTP codes or own codes between 600 and 700 for business logic errors)
data: { <result> }
}
*/
if (settings.dataType === 'json') {
if (response.status == 'success') {
// Just resolve and give data back
d.resolve(response.data);
} else if (response.status == 'error') {
// Implement error handling
d.reject(response.data);
}
} else {
d.resolve(response);
}
},
error: function (jqXHR, textStatus, errorThrown) {
console.log(jqXHR);
d.reject(jqXHR);
},
complete: d.resolve
});
$.ajax(jqXHRSettings);
});
var promise = deferred.promise();
promise.success = deferred.done;
promise.error = deferred.fail;
promise.complete = deferred.done;
return promise;
}
};
My implementation of this deferred function (not working!):
// Retrieve all sessions from fullcalendars
var ajax = Application.ajax({
url: Routing.generate($this.options.ajaxScheduleSessionsRoute, { _format: 'json', id: this.options.scheduleId }),
data: {
"rooms": $this._rooms // $this._rooms is an array! [1, 2, 3, 4, 5]
}
});
ajax.fail(function(jqXHR, textStatus, errorThrown){
console.log(jqXHR);
});
ajax.done(function(response, textStatus, jqXHR){
console.log(response);
});
The result (missing the [])
Default implementation of jQuery ajax before using above deferred function (this works!):
$.ajax({
type: 'POST',
url: Routing.generate($this.options.ajaxScheduleSessionsRoute, { _format: 'json', id: this.options.scheduleId }),
data: {
"rooms": $this._rooms
},
error: function(XMLHttpRequest, textStatus, errorThrown) {
console.log('status:' + XMLHttpRequest.status + ', status text: ' + XMLHttpRequest.statusText);
},
success: function(data) {
$.each(data, function( key, source ) {
var roomId = key;
console.log(source);
$('#calendar'+key).fullCalendar( 'addEventSource', source );
});
},
dataType: 'json'
});
The result (with the [])
The question:
Why is the default implementation with jQuery Ajax working and the deferred function is not?
Oh no, I submitted this question and afterwards I saw the traditional option in my deferred function :( I deleted it and it works great now. I could knew it was something stupid ;-)
So, dont use
var defaults = {
cache: false,
type: 'post',
traditional: true,
dataType: 'json'
},
But use
var defaults = {
cache: false,
type: 'post',
dataType: 'json'
},
In a jquery Ajax call I am currently handling statusCode of 200 and 304. But I also have "Error" defined" To catch any Errors that could come back.
If there is a validation message related we return the status code of 400 - Bad Request.
This then falls into the "Error" function before falling into the statusCode "400" function I had defined. Which means two actions happen.
Ideally I would like to not define "Error" and "Success" and only define "statusCode" But what I need is to have a "Else" so that I don't need to declare every statusCode that exists only the 2-3 I want to handle differently.
$.ajax({
type: 'POST',
contentType: "application/json",
url: "../API/Employees.svc/" + EmployeeId + "/Company/" + CompanyId,
data: jsonString,
statusCode: {
200: function () { //Employee_Company saved now updated
hideLoading();
ShowAlertMessage(SaveSuccessful, 2000);
$('#ManageEmployee').dialog('close');
},
304: function () { //Nothing to save to Employee_Company
hideLoading();
$('#ManageEmployee').dialog('close');
if (NothingToChange_Employee) {
ShowAlertMessage(NothingToUpdate, 2000);
} else {
ShowAlertMessage(SaveSuccessful, 2000);
}
}
},
error: function (XMLHttpRequest, textStatus, errorThrown) {
AjaxError(XMLHttpRequest, textStatus, errorThrown);
}
});
Since the "complete" event is always fired you could simply get the status code from there and ignore the success and error functions
complete: function(e, xhr, settings){
if(e.status === 200){
}else if(e.status === 304){
}else{
}
}
This is what i'd use:
error: function (xhr, textStatus, errorThrown) {
switch (xhr.status) {
case 401:
// handle unauthorized
break;
default:
AjaxError(xhr, textStatus, errorThrown);
break;
}
}
jQuery AJAX response complete, success, error have been deprecated. More up-to-date version with .done, .fail, .always promise instead.
On success .always has signature of .done, on failure it's signature changes to that of .fail. Using the textStatus you can grab the correct variable and return the body contents.
var jqxhr = $.ajax( {
type: frm.attr('method'),
url: frm.attr('action'),
data: frm.serialize(),
dataType: 'json',
} )
.done(function( data, textStatus, jqXHR ) {
alert( "success" );
})
.fail(function( jqXHR, textStatus, errorThrown ) {
alert( "error" );
})
.always(function( data_jqXHR, textStatus, jqXHR_errorThrown ) {
if (textStatus === 'success') {
var jqXHR = jqXHR_errorThrown;
} else {
var jqXHR = data_jqXHR;
}
var data = jqXHR.responseJSON;
switch (jqXHR.status) {
case 200:
case 201:
case 401:
default:
console.log(data);
break;
}
});
jqxhr.always(function() {
alert( "second complete" );
});
To keep the approach similar to your initial logic, I would continue passing a statusCode object. However, you still know that "else" will fall in the realm of 4xx or 5xx type error codes.
So I would update your original code to:
var statusCodeResponses = {
200: function () { //Employee_Company saved now updated
hideLoading();
ShowAlertMessage(SaveSuccessful, 2000);
$('#ManageEmployee').dialog('close');
},
304: function () { //Nothing to save to Employee_Company
hideLoading();
$('#ManageEmployee').dialog('close');
if (NothingToChange_Employee) {
ShowAlertMessage(NothingToUpdate, 2000);
} else {
ShowAlertMessage(SaveSuccessful, 2000);
}
}
};
var genericElseFunction = function(response){
// do whatever other action you wanted to take
};
for(var badResponseCode=400; badResponseCode<=599; badResponseCode++){
statusCodeResponses[badResponseCode] = genericElseFunction;
}
$.ajax({
type: 'POST',
contentType: "application/json",
url: "../API/Employees.svc/" + EmployeeId + "/Company/" + CompanyId,
data: jsonString,
statusCode: statusCodeResponses,
error: function (XMLHttpRequest, textStatus, errorThrown) {
AjaxError(XMLHttpRequest, textStatus, errorThrown);
}
});