Is there a way to abort all Ajax requests globally without a handle on the request object?
The reason I ask is that we have quite a complex application where we are running a number of different Ajax requests in the background by using setTimeOut(). If the user clicks a certain button we need to halt all ongoing requests.
You need to call abort() method:
var request = $.ajax({
type: 'POST',
url: 'someurl',
success: function(result){..........}
});
After that you can abort the request:
request.abort();
This way you need to create a variable for your ajax request and then you can use the abort method on that to abort the request any time.
Also have a look at:
Aborting Ajax
You cannot abort all active Ajax requests if you are not tracking the handles to them.
But if you are tracking it, then yes you can do it, by looping through your handlers and calling .abort() on each one.
You can use this script:
// $.xhrPool and $.ajaxSetup are the solution
$.xhrPool = [];
$.xhrPool.abortAll = function() {
$(this).each(function(idx, jqXHR) {
jqXHR.abort();
});
$.xhrPool = [];
};
$.ajaxSetup({
beforeSend: function(jqXHR) {
$.xhrPool.push(jqXHR);
},
complete: function(jqXHR) {
var index = $.xhrPool.indexOf(jqXHR);
if (index > -1) {
$.xhrPool.splice(index, 1);
}
}
});
Check the result at http://jsfiddle.net/s4pbn/3/.
This answer to a related question is what worked for me:
https://stackoverflow.com/a/10701856/5114
Note the first line where the #grr says: "Using ajaxSetup is not correct"
You can adapt his answer to add your own function to window if you want to call it yourself rather than use window.onbeforeunload as they do.
// Most of this is copied from #grr verbatim:
(function($) {
var xhrPool = [];
$(document).ajaxSend(function(e, jqXHR, options){
xhrPool.push(jqXHR);
});
$(document).ajaxComplete(function(e, jqXHR, options) {
xhrPool = $.grep(xhrPool, function(x){return x!=jqXHR});
});
// I changed the name of the abort function here:
window.abortAllMyAjaxRequests = function() {
$.each(xhrPool, function(idx, jqXHR) {
jqXHR.abort();
});
};
})(jQuery);
Then you can call window.abortAllMyAjaxRequests(); to abort them all. Make sure you add a .fail(jqXHRFailCallback) to your ajax requests. The callback will get 'abort' as textStatus so you know what happened:
function jqXHRFailCallback(jqXHR, textStatus){
// textStatus === 'abort'
}
Related
I am trying to make search function based on Ajax/Jquery.
My web app shows the data of service requests from the database. I want to make searchbar for my app as follows:
show all service request on the table initially.
If something is typed on the searchbar, it searches data and load those data to the table.
Finally if user deletes anyword from searchbar it will show all data as stated on No.1
I managed doing second and third function but I am having issues with the first one.
$(document).ready(function(){
$('#search_text').keyup(function(){
var txt = $(this).val();
if(txt != '') {
$.ajax({
url:"ajax/fetchRequests.php",
method:"post",
data:{search:txt},
dataType:"text",
success:function(data) {
$('#result').html(data);
}
});
}
else if(txt == '') {
$.get("ajax/readRequests.php", {}, function (data, status) {
$("#result").html(data);
});
}
});
});
Here is another script that i have worked on trying:
$(document).ready(function(){
var txt = $('#search_text').val();
if(txt != ''){
$.ajax({
url:"ajax/fetchRequests.php",
method:"post",
data:{search:txt},
dataType:"text",
success:function(data) {
$('#result').html(data);
}
});
}
else if(txt == '') {
$.get("ajax/readRequests.php", {}, function (data, status) {
$("#result").html(data);
});
}
});
All my features are working except for the search functions. Any tips or critics are welcome, thank you very much in advance.
I suggest you do two things, 1) use the suggested .on() and 2) use only one ajax function to simplify things. The idea is to funnel your calls through one function so that you know if something fails, it's not because you messed up the ajax part of the script:
// Create a generic ajax function so you can easily re-use it
function fetchResults($,path,method,data,func)
{
$.ajax({
url: path,
type: method,
data: data,
success:function(response) {
func(response);
}
});
}
// Create a simple function to return your proper path
function getDefaultPath(type)
{
return 'ajax/'+type+'Requests.php';
}
$(document).ready(function(){
// When the document is ready, run the read ajax
fetchResults($, getDefaultPath('read'), 'post', false, function(response) {
$('#result').html(response);
});
// On keyup
$(this).on('keyup','#search_text',function(){
// Get the value either way
var getText = $(this).val();
// If empty, use "read" else use "fetch"
var setPath = (!getText)? 'read' : 'fetch';
// Choose method, though I think post would be better to use in both instances...
var type = (!getText)? 'post' : 'get';
// Run the keyup function, this time with dynamic arguments
fetchResults($, getDefaultPath(setPath), type, { search: getText },function(response) {
$('#result').html(response);
});
});
});
To get initial results hook onto jQuery's document ready event.
var xhr;
var searchTypingTimer;
$(document).ready(function(){
// initial load of results
fetchResults([put your own params here]);
// apply on change event
$('#search_text').on('input', function() {
clearTimeout(typingTimer);
searchTypingTimer = setTimeout(fetchResults, 300);
});
});
function fetchResults($,path,method,data,func)
{
if (xhr && xhr.readyState != 4){
xhr.abort();
}
xhr = $.ajax({
url: path,
type: method,
data: data,
success:function(response) {
func(response);
}
});
}
As Rasclatt mentions you should use jQuery's on method to catch any changes.
Secondly I'd recommend disposing of previous requests when you make new ones, since if you are sending a new one on each character change then for one word many requests will be made. They won't necessarily arrive back in the order you send them. So for example as you type 'search term', the result for 'search ter' may arrive after and replace 'search term'. (welcome to async).
Thirdly since you will send many requests in quick succession I'd only call your fetchResults function after a short time out, so for example if a user types a five character word it doesn't fire until 300ms after the last character is typed. This will prevent 4 unnecessary requests that would just be ignored but put strain on your backend.
I want to set timeout after 2 seconds loading data. I am new in ajax so please clarify through my code...because i have already see many (set time out on ajax) answer but every one do through $.ajax().
how I can do through .load() ? It is possible or not ?
My AJAX code 1:
// Start of our new ajax code
if (!url) {
url = jQuery('#product_addtocart_form').attr('action');
}
url = url.replace("checkout/cart","ajax/index"); // New Code
var data = jQuery('#product_addtocart_form').serialize();
data += '&isAjax=1';
jQuery('#ajax_loader').show();
try {
jQuery.ajax( {
url : url,
dataType : 'json',
type : 'post',
data : data,
success : function(data) {
jQuery('#ajax_loader').hide();
parent.setAjaxData(data,true);
}
});
jQuery("#productOptions").modal('hide');
} catch (e) {
//alert(e);
}
// End of our new ajax code
2:
// AJAX product options modal
$('.optionsTrigger').on('click', function() {
var target, url;
target = $(this).attr('data-target');
url = $(this).attr('href');
$(target).load(url, function(){
$(target).modal({
show: true
});
});
});
$('#productOptions').on('hidden', function() {
$('#productOptions').html('<img src="<?php echo $this->getSkinUrl("img/loading.gif"); ?>" id="optionsLoading" />');
window.setTimeout("Tick()", 2000);
function Tick()
{
}
});
jQuery has the ajaxSetup() method available. You can set all options to the normal ajax() method there, including the timeout option. The settings set there should also be available when you call your AJAX request via load().
First, wrap your head around the fact that Ajax is asynchronous (like setTimeout) - the callbacks are called somewhen in the future.
How to timeout? You could use
var request = jQuery.ajax(…);
setTimeout(function() {
request.abort();
}, 2000);
request.done(function callback(){ … });
But it's much simpler than that, jQuery already has a timeout parameter for it's ajax() option object.
However, this is not possible using load - here not the jqXHR object is returned, but the current jQuery DOM-selection. Either, you have to globally configure ajax, or you don't use load and build the method yourself - it's not that hard, see source
I'm having an issue with my update button and jquery ajax. Right now when I click on my update button, it saves whatever updated data to the database. My goal is I want to slide up a message if the update is successful. I was looking at ajax post and using the success event seems like it would work but I dont know how to incorporte it. How would I do this? Would it be something like this?
$(document).ready(function(){
$('#divSuccess').hide();
$('#btnUpdate').click( function() {
alert('button click');
$.ajax({
url: "test.aspx",
context: document.body,
success: function(){
$('#divSuccess').show("slide", { direction: "down" }, 3000);
$('#divSuccess').hide("slide", { direction: "down"}, 5000);
}
});
});
});
check out this question for an example on how to handle the success event. Hope this helps!
$("#targetDiv").load("page.php",$("#form").serializeArray(),function (response)
{
if (response == '0' && response != '')
alert('Request not sent to server !\n');
else if(response == '-1')
alert('Please write some more !\n');
else
{
alert("success! ");
}
}
);
i've echo ed 0 and -1 for failure and other for success
In the jquery post function, you can execute some callback function.
function (data, textStatus) {
// data could be xmlDoc, jsonObj, html, text, etc...
this; // the options for this ajax request
// textStatus can be one of:
// "timeout"
// "error"
// "notmodified"
// "success"
// "parsererror"
// NOTE: Apparently, only "success" is returned when you make
// an Ajax call in this way. Other errors silently fail.
// See above note about using $.ajax.
}
http://docs.jquery.com/Post
With at least jQuery 1.5, you've got deferred objects and new syntax for AJAX events (including success).
var $ajaxcall = $.ajax({
url : 'myurl.svc/somemethod',
data : '{ somedata : "sometext" }'
});
$ajaxcall.success(function() {
// do something on successful AJAX completion
});
Of course you can chain that as well, and call something along the lines of $.ajax().success() or something.
Just wrote a blog post on it myself, if you're interested in reading more.
I have a simple jQuery function that resizes text areas, and I want it to apply to all text areas.
For the most part, this works great:
$(document.ready(function(){$("text_area").resizer('250px')});
However, because it is only called once when the document is ready, it fails to catch text areas that are later added onto the page using Ajax. I looked at the .live() function, which seems very close to what I'm looking. However, .live() must be bound to a specific event, whereas I just need this to fire once when they're done loading (the onLoad event doesn't work for individual elements).
The only thing I can get working is a really obtrusive inclusion of the JavaScript call directly into the Ajax. Is that the recommended way to be doing this?
Edit: Here is the rails source code for what it does for Ajax requests:
$('a[data-confirm], a[data-method], a[data-remote]').live('click.rails', function(e) {
var link = $(this);
if (!allowAction(link)) return false;
if (link.attr('data-remote') != undefined) {
handleRemote(link);
return false;
} else if (link.attr('data-method')) {
handleMethod(link);
return false;
}
});
// Submits "remote" forms and links with ajax
function handleRemote(element) {
var method, url, data,
dataType = element.attr('data-type') || ($.ajaxSettings && $.ajaxSettings.dataType);
if (element.is('form')) {
method = element.attr('method');
url = element.attr('action');
data = element.serializeArray();
// memoized value from clicked submit button
var button = element.data('ujs:submit-button');
if (button) {
data.push(button);
element.data('ujs:submit-button', null);
}
} else {
method = element.attr('data-method');
url = element.attr('href');
data = null;
}
$.ajax({
url: url, type: method || 'GET', data: data, dataType: dataType,
// stopping the "ajax:beforeSend" event will cancel the ajax request
beforeSend: function(xhr, settings) {
if (settings.dataType === undefined) {
xhr.setRequestHeader('accept', '*/*;q=0.5, ' + settings.accepts.script);
}
return fire(element, 'ajax:beforeSend', [xhr, settings]);
},
success: function(data, status, xhr) {
element.trigger('ajax:success', [data, status, xhr]);
},
complete: function(xhr, status) {
element.trigger('ajax:complete', [xhr, status]);
},
error: function(xhr, status, error) {
element.trigger('ajax:error', [xhr, status, error]);
}
});
}
So in my particular case, I've got a link, that has data-remote set to true, which points to a location that will return JavaScript instructing a form containing a text area to be appended to my document.
A simple way to do this would be to use ajaxComplete, which is fired after every AJAX request:
$(document).ajaxComplete(function() {
$('textarea:not(.processed)').resizer('250px');
});
That says "every time an AJAX request completes, find all textarea elements that don't have the processed class (which seems to be added by the resizer plugin -- terrible name for its purpose!) and call the resizer plugin on them.
You may be able to optimise this further if we could see your AJAX call.
Generally speaking, I would do it this way..
$.ajax({
type : "GET",
url : "/loadstuff",
success: function(responseHtml) {
var div = $("#containerDiv").append(responseHtml);
$("textarea", div).resizer("250px");
}
});
Wondering if you could use .load for this. For example:
$('text_area').load(function() {
$("text_area").resizer('250px');
});
I'm making an ajax call like this:
var requestData = function() {
$.ajax({
dataType: 'jsonp',
jsonp: 'js',
url: "http://someServer",
success: function (data) {
// do stuff with data
},
complete : function(data) {
// try again in 5 seconds
setTimeout(requestData, 5000);
}
});
};
All is well and good, and it works, EXCEPT: the server is a bit flaky, and from time to time, it fails to return a response. That's fine, but when that happens, the complete handler never fires. I've also tried using an error handler. Is there something else I can do? I've thought about using setInterval, but I'd really rather it do the next one after this one, not at a set time where they might pile up....
UPDATE: when the server fails, I get "Failed to load resource" in chrome's console.
The problem is that JSONP works by inserting a script tag into the DOM, rather than by XMLHTTPRequest. script tags have no onerror property, so you can't test for success by conventional methods. The only way to do it is via a timeout.
Something like this might work:
var requestComplete = {};
var requestData = function() {
var now = (new Date()).getTime();
requestComplete[now] = false;
$.ajax({
dataType: 'jsonp',
jsonp: 'js',
url: "http://someServer",
success: function (data) {
requestComplete[now] = true;
// do stuff with data
}
});
setTimeout(function() {
if (!requestComplete[now]) {
setTimeout(requestData, 5000); // try again in 5 seconds
}
}, 5000); // give the JSONP request 5 seconds to work
};