jjaappoo jjaappoo - 2 months ago 7
Javascript Question

Parallel calls $.when with $.ajax() not working

I was trying to make parallel calls using the jQuery method $.when

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
<title>Sample Title</title>
</head>
<body>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"> </script>
<script>
$.when(
// Get the first call
$.ajax("delay_test.php"),

// Get the second call
$.ajax("delay_test.php")
).then(function(first,second) {
$("body").append("Done: "+first[0]+"<br>Done: "+second[0]);
});
</script>
</body>
</html>


I made also a php code for test this and see if it was really avoiding make the second call after the first one had finished.

<?php
sleep(5);
echo date("H:i:s");
?>


But what I am receiving is the 5 seconds difference:

Done: 15:27:55
Done: 15:28:00


Is there something I doing wrong or misunderstanding?

Answer

Firstly, let me say you can resolve your issue by using cache:false with your AJAX requests:

$.when(
  // Get the first call
  $.ajax({url:"delay.php",cache:false}),
  // Get the second call
  $.ajax({url:"delay.php",cache:false})
).then(function(first,second) {
  $("body").append("Done: "+first[0]+"<br>Done: "+second[0]);
});

Now let me expand by saying I'm not quite sure why. Something about chrome awaiting the result of the first AJAX request to send the second; perhaps waiting to see if it should pull the result from cache. Perhaps someone more enlightened with Chrome could say why. I did not have the issue in IE 11, and I did not test FireFox, Safari, Opera, etc.

Alternatively, you can append a GET variable to the end of the URL if you don't want to use an object and define url and cache (the cache:false option just appends a timestamp to the URLs to make them unique). Something like:

$.when(
  // Get the first call
  $.ajax("delay.php?r1"),
  // Get the second call
  $.ajax("delay.php?r2")
).then(function(first,second) {
  $("body").append("Done: "+first[0]+"<br>Done: "+second[0]);
});

Edit: Another alternative is to set no-cache headers in your PHP script. If you use this method, you'll likely have to clear your cache first, as your browser probably cached it already:

header("Cache-Control: no-store, no-cache, must-revalidate, max-age=0");
header("Cache-Control: post-check=0, pre-check=0", false);
header("Pragma: no-cache");

Nevermind the above suggestion - didn't work in my testing.