Patch: XHR requests that can stop if new requests are made
In my website, I'm using jQuery to handle XHR requests (using the
methods $.post, $.get, $.getScript and even the AJAX form plugin).
I wanted XHR requests to stop if new ones are made.
I've found a plugin named "AJAX Manager" (or something similar) for
that, but it was not what I was looking for: first, it supports just
$.get requests and it keeps all the active requests in a sort of
queue.
I needed something that stopped all the previous XHR requests when a
new one is made.
I thought the best way to accomplish that was simply not to trigger
the callback after the request completes.
I looked inside the jQuery library and I found that the problem could
not be solved with a plugin (I needed to edit the $.ajax method
directly).
So, I've realized a simple but powerful patch.
I'm posting the patch here: I hope it will be useful.
Also, since I think it's a quite useful addition, I'm asking the
developers wheter they could add it to the trunk.
Here's the patch (from my SVN repository):
Index: jquery.js
===================================================================
--- jquery.js (revision 188)
+++ jquery.js (revision 190)
@@ -2512,6 +2512,9 @@
var jsc = now();
jQuery.extend({
+ // The current request
+ ajaxRequestId: 0,
+
get: function( url, data, callback, type ) {
// shift arguments if data argument was ommited
if ( jQuery.isFunction( data ) ) {
@@ -2564,6 +2567,8 @@
processData: true,
async: true,
data: null,
+ newRequestAbort: false,
+ requestId: 0,
username: null,
password: null,
accepts: {
@@ -2586,6 +2591,10 @@
var jsonp, jsre = /=\?(&|$)/g, status, data,
type = s.type.toUpperCase();
+
+ // increment the request counter
+ jQuery.ajaxRequestId++;
+ s.requestId = jQuery.ajaxRequestId;
// convert data if not already a string
if ( s.data && s.processData && typeof s.data != "string" )
@@ -2813,9 +2822,12 @@
onreadystatechange();
function success(){
- // If a local callback was specified, fire it and pass it the data
- if ( s.success )
- s.success( data, status );
+ if(!s.newRequestAbort || s.requestId == jQuery.ajaxRequestId)
+ {
+ // If a local callback was specified, fire it and pass it the
data
+ if ( s.success )
+ s.success( data, status );
+ }
// Fire the global callback
if ( s.global )
@@ -2842,7 +2854,7 @@
handleError: function( s, xhr, status, e ) {
// If a local callback was specified, fire it
- if ( s.error ) s.error( xhr, status, e );
+ if ( s.error && (!s.newRequestAbort || s.requestId ==
jQuery.ajaxRequestId) ) s.error( xhr, status, e );
// Fire the global callback
if ( s.global )
Here's a test file
<?php
if(!empty($_GET['ajax']))
{
sleep(3);
echo "Received ".$_GET['ajax'];
exit;
}
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://
www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Untitled Document</title>
<script type="text/javascript" src="app/clientscript/jquery.js"></
script>
<script type="text/javascript">
//<!--
var id = 0;
function theCallback(data)
{
$("#result").append(data+"<br/>");
}
function doRequest(abort)
{
id++;
if(!abort)
{
$.ajaxSetup({newRequestAbort: false});
}
else
{
$.ajaxSetup({newRequestAbort: true});
}
$.get("test.php", {ajax: id}, theCallback);
}
//-->
</script>
</head>
<body>
<a href="javascript:doRequest(true)">do request that aborts on new
request</a><br />
<a href="javascript:doRequest(false)">do request that does NOT abort
on new requests</a>
<div id="result"></div>
</body>
</html>
I hope my work can help many other users that every day choose this
fantastic javascript framework.