0

I have a locally hosted project with a view that makes an AJAX request to the server. The code is duplicated in this jsfiddle, sans the URL and data params which are replaced w/ jsfiddle test data to mimic the AJAX request.

(function demo(iteration) {
    count = iteration || 0;
  
  if (count < 3) {
    $.when(testPromise(count).promise())
        .done(function () {
        doSomething();
        })
      .always(function () {
        demo(count + 1);
        });
  }
})();

function doSomething() {
    console.log("something!");
}

function testPromise(iteration) {
  var deferred = $.ajax({
    type: 'POST',
    url: '/echo/json/',
    data: {
      json: JSON.stringify({ "data": "Data!" }),
      delay: 0.1
    },
    dataType: 'json',
    beforeSend: function () {
            console.log("Before Send: " + iteration);
    },
    success: function(response) {
      console.log("Success: " + iteration);
    },
    error: function() {
        console.log("Error: " + iteration);
    },
    complete: function () {
        console.log("Complete: " + iteration);
    }
  });
  
  return deferred;
}

Now, the Jsfiddle makes the following print statements:

jsfiddle output

However, my local code makes an alternative set of print statements:

local output

You'll notice that the jsfiddle consecutive AJAX requests are issued and completed in order, but the local output shows that consecutive requests are issued before the previous one completes: Before Send: 1; Complete: 0 and Before Send: 2; Complete: 1. That is, the Promise callback and Complete callback are not handled in the same order for these two environments.

According to http://api.jquery.com/jquery.ajax/,

The callback hooks provided by $.ajax() are as follows:

  1. beforeSend callback option is invoked.
  2. error ...
  3. dataFilter ...
  4. success callback option is invoked, if the request succeeds.
  5. Promise callbacks — .done(), .fail(), .always(), and .then() — are invoked, in the order they are registered.
  6. complete callback option fires, when the request finishes, whether in failure or success.

Besides the list order, the documentation does not really indicate whether the order of these callbacks is guaranteed and I would suppose that the order is actually not guaranteed given that the jsfiddle and my local code do not reconcile.

So what is happening under the covers to produce these two different results? And suppose I wanted my local code to behave like the jsfiddle (Complete handled before Promise) - what changes can I make to accomplish this?

Thanks in advance -

As a sidenote, I am aware that the following $.when() functionality can be achieved via the AJAX .complete() handler. I have intentionally made the AJAX function agnostic to the conditions for which it would need to be called as the end goal I have is to make a generic queue'ing module which will handle queue processing and call a given deferrable function as necessary. So, the AJAX .complete() method is not available to me for this purpose.

$.when(testPromise(count).promise())
    .done(function () {
        doSomething();
    })
    .always(function () {
        demo(count + 1);
    });
7
  • ajax is asynchronous. The server can impact the order that responses are received in which is likely why you are getting different results in jsfiddle compared to your own server. Commented Jun 26, 2017 at 21:03
  • that is true, although I wouldn't expect the server response to matter in this situation since each subsequent request is dependent on the previous request's deferred object having already resolved. So b/c only one ajax request has a deferred object state of "pending" at any given time, the server should be irrelevant. Please correct me if I'm wrong but I appreciate the input! Commented Jun 26, 2017 at 21:47
  • If that is the case, then yeah the server's response would be irrelevant. Can you provide the relevant code in your question? Commented Jun 26, 2017 at 21:47
  • Everything is in that jsfiddle Commented Jun 26, 2017 at 21:50
  • 1
    Assuming both locations are using the same version of jquery, I can't explain why one would give different results than the other in this case. Commented Jun 26, 2017 at 21:56

1 Answer 1

1

jQuery Deferred was updated in version 3.0 (https://blog.jquery.com/2016/06/09/jquery-3-0-final-released/), so making sure your jQuery version is the same as on the fiddle (3.2.1) may help.

Sign up to request clarification or add additional context in comments.

1 Comment

Huh, yep - well I didn't anticipate versioning to be an issue as the deferred object documentation did not mention a mechanics change from 2.X to 3.X but you are absolutely correct. My environ is on 2.2 and when I bump the jsfiddle down to 2.4 it behaves exactly like my local codebase. Silly me. Thanks for the reply

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.