jQuery: Submit a form only if no AJAX is currently running on the page

后端 未结 5 1304
野趣味
野趣味 2021-01-13 19:44

When the city input field is blurred I get somnething via an ajax request and set that as the value of a hidden field in the same form that the city field resides in.

<
5条回答
  •  深忆病人
    2021-01-13 20:20

    Use jQuery's Ajax Events. As long as all of your Ajax calls are generated using jQuery, you have a way of knowing if any Ajax calls are outstanding.

    $(document).ready(function() {
        var ajaxBusy = false;
    
        $(document).ajaxStart( function() { 
            ajaxBusy = true; 
        }).ajaxStop( function() {
            ajaxBusy = false;
        });
    });
    

    Edit:

    So that answers your direct question about "How do I know if there is any Ajax call running."

    Alternatively, you could disable the form's submit buttons when run your blur handler, and then re-enable it when you're done.

    $('input#city').on('blur', function() {
        var submit = $(this).closest('form').find(':submit:enabled');
        submit.prop('disabled', true);
        $.ajax('get/something?param=val').done(function(response) {
            $('input:hidden[name="something"]').val(response);
        }).always(function() {
            submit.prop('disabled', false);
        });
    });
    

    Edit 2:

    So now we're at the point where we would like to delay the form submission until all current Ajax calls have completed. We let people click on the submit button, but if there are pending Ajax calls we don't do anything right away.

    We can use a Deferred object to help us with this.

    $(document).ready(function() {
        var ajaxDefer = $.Deferred().resolve();
    
        $(document).ajaxStart( function() { 
            ajaxDefer = $.Deferred(); 
        }).ajaxStop( function() {
            ajaxDefer.resolve();
        });
    
        $('form#find-users').on('submit', function() {
            ajaxDefer.always(function() {
                // Code here will always be executed as soon as there are no 
                // Ajax calls running.
                // this points to the deferred object (ajaxDefer), so use the closure
                // to carry over any variables you need.
            });
        });
    });
    
    1. When we're just starting out, we set up our ajaxDefer object in a resolved state. That means any functions attached using .always() will execute immediately.

    2. When the first Ajax call starts, we replace the old ajaxDefer object with a new one that has not been resolved. Any new functions attached using ajaxDefer.always() will be deferred until later.

    3. When the last Ajax call completes, we call ajaxDefer.resolve(), which causes any unexecuted deferred functions to execute. Now we're back to our initial state, where any newly-attached functions will execute immediately.

    4. When somebody tries to submit the form, create an anonymous function that does the work and attach it to ajaxDefer. It will get executed when appropriate, depending on if there are any outstanding Ajax requests or not. Be mindful of your closures.

提交回复
热议问题