I am using JQuery when. The syntax looks like this:
$.when(
// Get the HTML
$.get("/feature/", function(html) {
globalStore.html = html;
}),
// Get the CSS
$.get("/assets/feature.css", function(css) {
globalStore.css = css;
}),
// Get the JS
$.getScript("/assets/feature.js")
).then(function() {
// Add CSS to page
$("<style />").html(globalStore.css).appendTo("head");
// Add HTML to page
$("body").append(globalStore.html);
});
My question
How can I do error handling when one of the call to the server results in exception (failure scenario) or error handling for any other scenario?
Since I am making Ajax request here, how can I define timeout period for the Ajax request?
deferred.then( doneCallbacks, failCallbacks ) can take a failure filter like
$.when(
// Get the HTML
$.get("/feature/", function(html) {
globalStore.html = html;
}),
// Get the CSS
$.get("/assets/feature.css", function(css) {
globalStore.css = css;
}),
// Get the JS
$.getScript("/assets/feature.js")
).then(function() {
// Add CSS to page
$("<style />").html(globalStore.css).appendTo("head");
// Add HTML to page
$("body").append(globalStore.html);
}, function(){
//there is an exception in the request
});
To setup the timeout, you can use the timeout option.
You can use it either globally like
jQuery.ajaxSetup({
timeout: 5000
})
or use $.ajax() instead of the short version $.get() with the timeout option
I think it is because the calls are async. When using:
$.ajax({
url: "file.php",
type: "POST",
async: false,
success: function(data) {
}
});
The call is synchronous.
Related
I am working on a web application for debtor management and I am refactoring the code and try to adhere to the principle of separation of concerns. But the async nature of AJAX is giving me headaches.
From a jQuery dialog the user can set a flag for a debtor which is then stored in a database. If that succeeds, the dialog shows a notification. Until now I handled everything inside the jQuery Ajax success callback function: validating input, doing the ajax request and updating the content of the dialog.
Of course this lead to spaghetti code.
Thus I created a class AjaxHandler with a static method for setting the flag, which is invoked by the dialog. I thought that the dialog could update itself according the the return value of the AjaxHandler but I did not have the asynchronity in mind.
The following question was helpful in tackling the return values.
How do I return the response from an asynchronous call?
But how can I update the dialog without violating the SoC principle?
EDIT
$("#button").on("click", function() {
var returnValue = AjaxHandler.setFlag();
if(returnValue) { $("#div").html("Flag set"); }
else { $('#div").html("Error setting flag");
});
class AjaxHandler {
static setFlag(){
$.ajax({
type: "POST",
url: "ajax/set_flag.php",
success: function(returndata){
return returndata; //I know this does not work because of
//ASYNC,but that is not the main point.
}
}
})
There is many ways to handle async responses, but the jQuery way is slightly different, so when you are already using jQuery, handle it this way:
$('#button').on('click', AjaxHandler.setFlag)
class AjaxHandler {
static setFlag () {
this.loading = true
this
.asyncReq('ajax/set_flag.php')
.done(function () {
$('#div').html('Flag set')
})
.fail(function (err) {
$('#div').html('Error setting flag. Reason: ' + err)
})
.always(function () {
this.loading = false
})
}
asyncReq (url) {
return $.ajax({
type: 'POST',
url: url
})
}
})
Consider using events perhaps here?
$("#button").on("click", function() {
$('body').trigger('getdata', ["", $('#div')]);
});
$('body').on('getdata', function(event, datasent, myelement) {
var attach = event.delegateTarget;// the body here
var getAjax = $.ajax({
type: "POST",
url: "ajax/set_flag.php",
data: datasent // in case you need to send something
})
.done(function(data) {
$(attach).trigger('gotdata', [data, myelement]);
});
getAjax.fail(function() {});
})
.on('gotdata', function(event, datathing, myelement) {
myelement.html(!!datathing ? "Flag set", "Error setting flag");
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
Note that inside those event handlers you could also call some function, pass a namespace for the function, basically do it as you please for your design.
I have a project which involves live notification. So I stumbled upon using socket io but I didn't have enough time to learn it yet. So I tried doing it with AJAX and jQuery. Below is my code structure and I was wondering if this is gonna work with no drawbacks?
setInterval(function(){
if( !element.hasClass('processing') ){
element.addClass('processing');
$.ajax({
type: 'post',
dataType: 'json',
url: ajaxurl,
data: {},
success: function( response ){
/* Success! */
element.removeClass('processing');
}
});
}
}, 2500);
Some Extra Info
The way you described will work. From Experience I would just like to point out some things.
I usually do a recursive function, allows you to wait your interval between ajax calls and not a fixed rate. //OPTIONAL BUT DOES GIVE THE SERVER SOME BREATHING ROOM.
Use window.setTimeout() with an isActive flag. //ALLOWS YOU TO STOP POLLING FOR WHATEVER REASON, AND BECAUSE FUNCTION IS RECURSIVE START UP AGAIN IF NEED BE
For Sake of being thorough, I found it is always a good idea to handle the error case of the $.ajax() post. You could perhaps display some message telling the user he is no longer connected to the internet etc.
Some Sample Code:
var isActive = true;
$().ready(function () {
//EITHER USE A GLOBAL VAR OR PLACE VAR IN HIDDEN FIELD
//IF FOR WHATEVER REASON YOU WANT TO STOP POLLING
pollServer();
});
function pollServer()
{
if (isActive)
{
window.setTimeout(function () {
$.ajax({
url: "...",
type: "POST",
success: function (result) {
//SUCCESS LOGIC
pollServer();
},
error: function () {
//ERROR HANDLING
pollServer();
}});
}, 2500);
}
}
NOTE
This is just some things I picked up using the exact method you are using, It seems that Web Sockets could be the better option and I will be diving into that in the near future.
Please refer :
Jquery : Ajax : How can I show loading dialog before start and close after close?
I hope this could help you
$("div.add_post a").click(function(){
var dlg = loadingDialog({modal : true, minHeight : 80, show : true});
dlg.dialog("show");
$.ajax({
url : "/add.php",
complete : function (){
dlg.dialog("hide");
}
});
return false;
});
//--Loading dialog
function loadingDialog(dOpts, text = "пожалуйста подождите, идет загрузка...")
{
var dlg = $("<div><img src='/theme/style/imgs/busy.gif' alt='загрузка'/> "+text+"<div>").dialog(dOpts);
$(".ui-dialog-titlebar").hide();
return dialog;
}
Hello guys here's my code:
var ajax={
chiamata:function(target,url,opzioni){
if (!tools.array_key_exists('caricamento',opzioni)){
opzioni['caricamento']=1;
}
var dati=url.split('?');
$.ajax({
type: opzioni['type'],
url: url,
contentType:"application/x-www-form-urlencoded; charset=UTF-8",
data: dati[1],
dataType: "html",
success: function(msg){
if (opzioni['caricamento']!=0){
ajax.printLoading();
}
$(target).html(msg);
},
error: function(){
alert("Chiamata fallita!");
}
})
},
printLoading:function(){
var body="#colonnaDX";
$(body).ajaxStart(function(){
$(body).append('<div id="loading"><img src="graphic/IMAGE/spinner.gif"/>Loading...</div>');
})
.ajaxStop(function(){
$('#loading').remove();
});
}
},
//Recursive function
var object={
checkAzione:function(target,url,opzioni,interval){
if (!interval)
interval=60000;
ajax.chiamata(target,url,opzioni);
setTimeout(function() {
this.checkAzione(target,url,opzioni,interval);
}, interval);
}
}
$(document).ready(function(){
object.checkAzione(
'#colonnaDX',
'someactions.php',{
'caricamento':0
},
10000
);
})
I'll try to explain the problem as better as i can, When the document is ready, the function "checkAzione" starts and it makes some stuff like DB calls etc, this kinds of ajax calls don't need any visual loading like spinner etc so in the array "opzioni" i set a flag 'caricamento':0 (same of 'loading':0) just check my ajax object to see what i mean, it works until i make some ajax calls that using 'caricamento':1, from that moment every ajax calls in my recursive function makes the "printLoading"... Any tips????
ajaxStart and ajaxStop are global, you add them to the body. You probably shouldn't use ajaxStart/Stop in this case, just add the functionality to your ajax listeners (success and error).
I want to execute a piece of javascript after the ajax response has been rendered. The javascript function is being generated dynamically during the ajax request, and is in the ajax response. 'complete' and 'success' events to not do the job. I inspected the ajax request in Firebug console and response hasn't been rendered when the complete callback executes.
Does not work:
function reloadForm() {
jQuery.ajax({
url: "<generate_form_url>",
type: "GET",
complete: custom_function_with_js_in_response()
});
};
ajaxComplete does the job, but it executes for all the ajax calls on the page. I want to avoid that. Is there a possible solution?
$('#link_form').ajaxComplete(function() {
custom_function_with_js_in_response();
});
you can also use $.ajax(..).done( do_things_here() );
$(document).ready(function() {
$('#obj').click(function() {
$.ajax({
url: "<url>"
}).done(function() {
do_something_here();
});
});
});
or is there another way
$(document).ready(function() {
$('#obj').click(function() {
$.ajax({
url: "<url>",
success: function(data){
do_something_with(data);
}
})
});
});
Please, utilize this engine for share your problem and try solutions. Its very efficient.
http://jsfiddle.net/qTDAv/7/ (PS: this contains a sample to try)
Hope to help
Checking (and deferring call if needed) and executing the existence of the callback function might work:
// undefine the function before the AJAX call
// replace myFunc with the name of the function to be executed on complete()
myFunc = null;
$.ajax({
...
complete: function() {
runCompleteCallback(myFunc);
},
...
});
function runCompleteCallback(_func) {
if(typeof _func == 'function') {
return _func();
}
setTimeout(function() {
runCompleteCallback(_func);
}, 100);
}
Can't help a lot without code. As an general example from JQuery ajax complete page
$('.log').ajaxComplete(function(e, xhr, settings) {
if (settings.url == 'ajax/test.html') {
$(this).text('Triggered ajaxComplete handler. The result is ' +
xhr.responseHTML);
}
});
In ajaxComplete, you can put decisions to filter the URL for which you want to write code.
Try to specify function name without () in ajax options:
function reloadForm() {
jQuery.ajax({
url: "<generate_form_url>",
type: "GET",
complete: custom_function_with_js_in_response
});
};
Sometimes in my application there are many elements loading so I want to show the typical AJAX spinner above the control (or DOM node) with it disabled.
What is the easiest/best way to do that?
Ideally I would like to:
$("#myelement").loading();
$("#myelement").finishloading();
Or even better being able to do AJAX requests directly with the element:
$("#myelement").post(url, params, myfunction);
Being #myelement a regular node or form input.
You could use beforeSend and complete callbacks:
$.ajax({
url: 'script.cgi',
type: 'POST',
beforeSend: function() {
$('.spinner').show();
},
complete: function() {
// will trigger even if request fails
$('.spinner').hide();
},
success: function(result) {
// todo: do something with the result
}
});
Since you're already using jQuery, you may want to look into BlockUI in conjunction with Darin Dimitrov's answer. I haven't used it yet myself as I just came across this today, but it looks decent.
If you're writing a semi-large-ish application and anticipate making many AJAX calls from different places in your code, I would suggest that you either add a layer of abstraction over $.ajax, or create a helper function to avoid having boiler plate for your UI indicator all over the place. This will help you out a lot should you ever need to change your indicator.
Abstraction method
var ajax = function(options) {
$.ajax($.extend(
{
beforeSend: function() {
$.blockUI();
},
complete: function() {
$.unblockUI();
}
},
options
));
};
ajax({
url: 'script.cgi',
type: 'POST',
success: function(result) {
// todo: do something with the result
});
Helper method
var ajaxSettings = function(options) {
return $.extend(
{
beforeSend: function() {
$.blockUI();
},
complete: function() {
$.unblockUI();
}
},
options
);
};
$.ajax(ajaxSettings({
url: 'script.cgi',
type: 'POST',
success: function(result) {
// todo: do something with the result
}
}));
Also, I wouldn't suggest overwriting the $.ajax method itself.
what i've done in the past is, on post pass the element id (a containing div) to a function which replaces it's inner HTML with a loading image, and then in the post back replace it's content again with the updated real content.
If you want to show the spinner every when an ajax call is in progress I think you should use ajaxStart and ajaxStop.
$("#spinner")
.ajaxStart(function(){$(this).show();})
.ajaxStop(function(){$(this).hide();});