0

When the user presses the 'Process' button on my application, I would like the application to trigger an AJAX request and then immediately redirect the user to another screen without waiting for the results of the AJAX request. I believe I have coded it appropriately but I notice that the screen is waiting for the AJAX to finish before redirecting. Am I missing something below?

$('#process-btn').on('click', function() 
{
    // disable the process & cancel buttons to prevent 
    // double submission or interruption
    $('#cancel-btn').addClass('disabled');
    $(this).addClass('disabled');

    // trigger the AJAX require to process the uploaded file on the server side
    $.ajax({
        url: $('#form').attr('action'),
        type: 'post',
        data: $('#form').serialize(),
        success: function() {
            //on success
        }
    });

    // redirect the user to view list
    // this line is not being called immediately - 
    // this is being called only after AJAX returns
    window.location.replace( www_root + 'Home/index' );
});
Lee Taylor
  • 7,761
  • 16
  • 33
  • 49
ChicagoSky
  • 1,290
  • 3
  • 22
  • 50
  • are you setting `async: false` in the ajax setup... try to set `async: true` in the ajax options and see – Arun P Johny Dec 19 '14 at 04:07
  • why not include the `window.location.replace( www_root + 'Home/index' );` in the ajax success function? Since you want to redirect based on the success result. – Aditya Dec 19 '14 at 04:08
  • what's the point of having `succes` block if you want to leave the page before succeed? – Verhaeren Dec 19 '14 at 04:08
  • @Aditya - no I want the redirect to occur regardless of the result. Notice that the redirect is outside the AJAX call – ChicagoSky Dec 19 '14 at 04:10
  • @Verhaeren - I can remove that - but is that the root cause of the issue? – ChicagoSky Dec 19 '14 at 04:10
  • Your `window.location.replace()` will be called before the `success` handler of the ajax function unless you've somehow made your ajax function to be synchronous. In fact, your page won't probably won't even still be running when the success handler runs. – jfriend00 Dec 19 '14 at 04:12
  • @jfriend00 and that is exactly what I want - but it doesnt seem to be happening – ChicagoSky Dec 19 '14 at 04:13
  • 1
    not sure if it is helpful or not,try to disable the default behaviour of `#process-btn` with `event.preventDefault()` – Kartikeya Khosla Dec 19 '14 at 04:18
  • @jfriend00 and I am here trolling and wasting everyone's time :) pointless.. – ChicagoSky Dec 19 '14 at 04:19
  • Any chance your button is a submit button and it's submitting a form. – jfriend00 Dec 19 '14 at 04:19
  • @jfriend00 bingo! yes it is a submit button - pls explain - does that interfere with the AJAX call? I am changing it to a regular button to see if i get a different result – ChicagoSky Dec 19 '14 at 04:21
  • @ChicagoSky...don't forget to read my comment above..there is no need to change submit button just use `event.preventDefault()` – Kartikeya Khosla Dec 19 '14 at 04:24
  • @Kartikeya - gave you reps – ChicagoSky Dec 19 '14 at 04:26
  • @Kartikeya - if they don't intend to ever submit the form via the default behavior, it's better to just not make it a submit button in the first place. No point in defining it as a submit button only to then block is with JS. – jfriend00 Dec 19 '14 at 04:30

2 Answers2

0

Because the button you have this handler hooked to is a submit button for a form (per your comments) and you aren't preventing the default behavior of that button, then the form submit will happen immediately and when the submit returns, it will change the page regardless of what your code tries to do.

So, the issue is that the returned form submit was overcoming what your code was trying to do.


You may be living a little dangerously by redirecting before your ajax call has finished. It's possible the browser could drop the ajax connection before the TCP buffers had actually been sent as TCP often has a small delay before sending buffers in order to collect consecutive data into common packets. It would be much safer to either redirect after a short timeout or redirect on the complete event which will be called regardless of ajax success.


If you really want to do the redirect BEFORE the ajax call has completed, you can experiment with the timeout value (shown here as set to 500ms) in this code to see what works reliably in multiple browsers:

$('#process-btn').on('click', function(e) {
    // prevent default form post
    e.preventDefault();

    // disable the process & cancel buttons to prevent 
    // double submission or interruption
    $('#cancel-btn').addClass('disabled');
    $(this).addClass('disabled');

    // trigger the AJAX require to process the uploaded file on the server side
    $.post($('#form').attr('action'), $('#form').serialize());

    // redirect the user to view list
    // this being called after a short delay to "try"
    // to get the form ajax call sent, but not "wait" for the server response
    setTimeout(function() {
        window.location.replace( www_root + 'Home/index' );
    }, 500);
});

Also, note that I've added an e.preventDefault() and added the e argument to the event handler to make sure the form is not posted by default, only by your ajax code.

And, the timeout time is set here to 500ms. What you need is enough time for the TCP infrastructure in the host computer to send all your form data before you start the redirect. I see a mention of a "file upload" in your comments. If this form is actually uploading a file, that could take way, way longer than 500ms. If it's just sending a few form fields, that should go pretty quickly assuming there are no connection hiccups.

Caveat: Doing it this way is not the 100% reliable way of getting data to your server. There can easily be some conditions where it takes longer than usual just to do a DNS lookup before connecting with your server or your server could momentarily take longer to respond to the initial connection before data can be sent to it. The only 100% reliable way is to wait until the ajax call has succeeded as mentioned elsewhere.

You could perhaps have the best of both worlds (reliability + fast response) if you changed the way your server processes the ajax call so that as soon as it has received the data, it returns a successful response (e.g. in milliseconds after receiving the data) and then after it has sent back the successful response so the browser can then reliably do its redirect, it takes it's 2-3 minutes to actually process the data. Remember, you don't gave to wait until you are done processing the request to return a response. Then, you know that the server has received the data, but the browser doesn't have to wait for the processing time. If you don't always want this ajax call to work that way, you can pass an argument to the ajax call to instruct the server whether you want the fast response or not.

jfriend00
  • 683,504
  • 96
  • 985
  • 979
  • Bingo!! Changed it from a submit button to a regular button and the redirect happened immediately. – ChicagoSky Dec 19 '14 at 04:24
  • 1
    This could be an comment in comment section. – Mangesh Parte Dec 19 '14 at 04:24
  • @MangeshParte - this is the answer. We figured this out in various comments and then I posted this as the answer. – jfriend00 Dec 19 '14 at 04:27
  • OMG what have this site became in. People just obsessed with what the site is for and how has to be used. The most of the comments are stating that kind of things. – Verhaeren Dec 19 '14 at 04:27
  • @ChicagoSky - please read my last paragraph. You may want to change how your redirect is done. – jfriend00 Dec 19 '14 at 04:28
  • understood - am looking into what you said. Question for you - if I understand what you are saying - essentially the AJAX call may never be triggered because the redirect could happen too soon. Hence, do the redirect in the complete event - did i get it right? – ChicagoSky Dec 19 '14 at 04:29
  • @ChicagoSky - yes, that's what I was suggesting. Remeber that the current JS execution context is suspended and then destroyed as soon as you start the redirect. Any open communication sockets (e.g. from Ajax calls) would be closed. – jfriend00 Dec 19 '14 at 04:31
  • @jfriend00 - having the complete function now delays the redirection until the AJAX call is complete (regardless of success or failure). Is there a way I can just have the script continue redirecting regardless of outcome (and still be safe with TCP like you mentioned? – ChicagoSky Jan 20 '15 at 04:21
  • @ChicagoSky - The last paragraph of my answer addresses that question I think. Anything other than not waiting for completion is a gamble that you would have to test in a lot of browsers and network situations to be sure you weren't redirecting too early. – jfriend00 Jan 20 '15 at 04:32
  • @jfriend00 - ok i understand, however now the call is "synchronous" isn't it. I mean the browser is stuck waiting for the call to complete - and my server side script takes about 2-3mins to complete. Can you please elaborate on how to create a short timeout before redirect in ajax call - would be obliged – ChicagoSky Jan 20 '15 at 04:41
  • Thanks @jfriend00 - The files are already uploaded and on the server by the time this button is pressed. So all that this button is sending as form information is a few checkboxes. I kept the delay to 3000ms just incase anyway. Side question - I noticed that unless I use `session_write_close()` on the server side PHP script, this ajax does not redirect event after the timeout. In other words its waiting for some end response from the server. Do you know why? – ChicagoSky Jan 20 '15 at 15:39
  • @ChicagoSky - are you preventing the form submission like I've advised? – jfriend00 Jan 20 '15 at 20:49
  • @jfriend00 how do I private message you? – ChicagoSky Jan 22 '15 at 02:04
  • @ChicagoSky - this system does not have private messaging. What else do you wish to ask? – jfriend00 Jan 22 '15 at 02:25
  • @jfriend00 i would like to share my code with you so that you can take a look and see if i am doing something incorrectly. There is some confidential code that i wish to not share online - hence the request to PM – ChicagoSky Jan 22 '15 at 02:28
-2

Why not try this:

  $.ajax({
        url: $('#form').attr('action'),
        type: 'post',
        data: $('#form').serialize(),
        success: function() {window.location.replace( www_root + 'Home/index' );}
  });
Verhaeren
  • 1,661
  • 9
  • 10
  • That would call `window.location.replace(...)` before the ajax call is even started, probably preventing it from even being started. You would need to pass a function reference, not the return result form executing `window.location.replace(...)` like `success: function() { window.location.replace(...)}`. – jfriend00 Dec 19 '14 at 04:13
  • Easy with the downvote guys. That button shouldn't even exist in a website that shows so much concern for peoples's feeling. Point the error, not need to humilliate me. Thanks. – Verhaeren Dec 19 '14 at 04:15
  • You can delete your erroneous answer to prevent further downvotes. This answer is clearly wrong - that's why the downvotes. – jfriend00 Dec 19 '14 at 04:17
  • How someone can pass `window.location.replace(...)` this as a parameter? – Mangesh Parte Dec 19 '14 at 04:18
  • @jfriend00 read my comment again, I'm not questioning the downvotes. The answer will stay so people see what is the wrong way of doing it. – Verhaeren Dec 19 '14 at 04:19
  • @jfriend00 And let the answer be there so people will see how much downvotes they get when someone post erroneous answers. – Mangesh Parte Dec 19 '14 at 04:20
  • That isn't how to do it here. You delete your erroneous answer once you realize it is wrong. It will continue to accumulate downvotes as long as you leave it here - that's what they are for - to show the community which answers are clearly wrong (if you don't delete it). – jfriend00 Dec 19 '14 at 04:20