0

I have a function that goes and grabs some information from a database and performs some logic using PHP, making this process take anywhere between 5 and 10 seconds for each of the results in the database - sometimes the whole process takes like 5 minutes total.

The only way of me knowing when all the process is finished is by using jQuery deferred calls, since it all runs asynchronously, but sometimes the user might want to stop this process and start over again with different parameters.

I have searched for how to stop these calls but can't find anything, I read about $deferObj.reject() but it's not working for me, I get $deferObj.reject is not a function

Basically all I want to do is to start the process, and when I click a Stop button then the deferred calls to stop. Right now this is not happening and for me to get out of there or even refresh to start over, it takes a bit of time while the rest of the deferred calls finish.

Here's my code that starts up the deferred calls:

    var getBooks = function( title ) {
        return $.ajax({
            url: 'ajax-handler.php',
            data: {action: 'get_books', title: title, params: $( '#params' ).val()},
            method: 'POST',
            dataType: 'json',
            success: function( results ) {
                if ( results.error ) {
                    console.log( 'Got an error processing ' + title );
                }
            }
        });
    }

    var books = new Array( 'Book 1', 'Book 2', 'Book 3', 'Book4' );
    var defBooks = new Array();
    for ( var i = 0; i < books.length; i++ ) {
        defBooks.push( getBooks( books[ i ] ) );
    }

    deferBooks = $.when.apply( $, defBooks );
    deferBooks.done( function() {
        alert( 'Process finished correctly' );
    }).fail( function () {
        alert( 'Process failed' );
    });

This code works just fine, I only get a Process failed message when I either have network issues or just something wrong in my PHP code, so everything needed to be done in the backend is being done.

Now, I also have a Stop Process button, that's supposed to stop all executions and allow me to start over, here's the code for that button's click event:

$( document ).on( 'click', '#stop-button', function() {
    deferBooks.reject(); // this one gives me the **deferBooks.reject is not a function** error message in the console
});

Please note that the deferBooks variable I have tried declaring it at the very top of my scripts file so that it's available in all functions, that's why I don't get a deferBooks is undefined message.

I'm out of ideas, this is my first time using deferred calls, so I might be missing something obvious...

Anyone who can give me some guidance on this?

Thanks

andrux
  • 2,782
  • 3
  • 22
  • 31
  • 1
    Once an AJAX request is sent, you cannot stop it from being processed. The closest analogy is like trying to stop a bullet after it's been fired. – Rory McCrossan May 09 '15 at 19:39
  • Ok, so that means all functions calls in defBooks.push( getBooks( books[ i ] ) ); are already running when I click the stop button? Should I be better off using synchronous calls for that? – andrux May 09 '15 at 19:52
  • Actually now that I think of it it is pretty obvious... what I'm storing in my defBooks array are whatever that function returns for each of the books, meaning all functions are already running.... – andrux May 09 '15 at 19:55
  • Ok, so, if I go with the synchronous option it will mean the code will be stuck at the defBooks.push( getBooks( books[ i ] ) ); part until each and everyone of those ends... not many options then... any idea of what I can do to implement a "Stop" button? – andrux May 09 '15 at 19:57
  • 2
    No, never use synchronous calls for anything. They're extremely bad practice. As for a stop button, there's not really anything you can do. You can re-enable any buttons which are disabled while the request is running, but the server will still be processing the request. The UI simply won't be listening for the return when it comes. – Rory McCrossan May 09 '15 at 19:57
  • Amen to that, using synchronous calls would defeat the very purpose of AJAX calls – andrux May 09 '15 at 19:58
  • That's the way I had it before, I was using bootstrap's $.button( 'loading' ) to disable the submit button.. I guess I will have to go back to that then, thanks, Rory – andrux May 09 '15 at 20:00
  • By the way, not sure why the question was downvoted, it's a valid question - dumb but valid - and I provided all details.. anyway, Rory, would you mind adding your comment as an answer so I can accept it? – andrux May 09 '15 at 20:02
  • added for you. Also upvoted too as the question has merit. Not sure why it was downvoted. – Rory McCrossan May 09 '15 at 22:28

2 Answers2

0

Once an AJAX request is sent, you cannot stop it from being processed. The closest analogy is like trying to stop a bullet after it's been fired.

Should I be better off using synchronous calls for that?

No, never use synchronous calls for anything. They're extremely bad practice. As for a stop button, there's not really anything you can do. You can re-enable any buttons which are disabled while the request is running, but the server will still be processing the request. The UI simply won't be listening for the return when it comes.

Rory McCrossan
  • 331,213
  • 40
  • 305
  • 339
0

jQuery ajax calls return a combination promise and jQuery ajax object. Besides the promise methods, it also has a .abort() method. This will "cancel" the ajax call and result in the promise being rejected.

Cancelling an ajax call that has already been sent to the server probably doesn't actually have any effect on your server since the request may already be underway on the server (the details depend upon your server implementation and how many requests it actually has underway). But, it does stop your success handlers from processing the result.

Since you have all the jQuery ajax objects in defBooks, you could do this:

// to cancel, you could do this:
defBooks.forEach(function(item) {
    item.abort();
});

Related answers:

Abort Ajax requests using jQuery

How to cancel/abort jQuery AJAX request?


If you want a bit finer grained control over the cancellation on your server, then you would have to change how you send your ajax calls so you don't send them all at once. Instead, you would sequence them one after the other. Then, you could just abort the ajax call that was currently in play and the others would then not be sent.

Community
  • 1
  • 1
jfriend00
  • 683,504
  • 96
  • 985
  • 979