0

In my web app I'm using a dialog with a spinner to indicate that the app is waiting for a server response. It's supposed that by clicking on Cancel button a user may stop waiting for the response.

I implemented this like the following:

function waitForResponse () {
    // pull jsons until it's ok
    $.ajax({
        url: ...,
        dataType: 'json'
    }).done(function (rsp, status) {
        // OK. Close the wait dialog.
        $('div#waitdialog').dialog('close');
    }).fail(function (rspobj, status, msg) {
        // Not yet. Pull it again.
        setTimeout(waitForResponse, 3000);
    });
}

$('<div id="waitdialog">')
    .appendTo('body')
    .append(spinner())
    .dialog({
        buttons: {
            Cancel: function () {
                $(this).dialog("close");
            }
        },
        close: function (event, ui) {
            $(this).remove();
        }
    });

waitForResponse();

The problem is I have no idea how to stop pulling jsons on Cancel click. I'd use a global variable, however I don't think this is good approach.

UPD. The question is not about how to stop an ajax request. It's about how to notify the pulling procedure in proper way avoiding global variables.

Rom098
  • 2,445
  • 4
  • 35
  • 52
  • possible duplicate of [Abort Ajax requests using jQuery](http://stackoverflow.com/questions/446594/abort-ajax-requests-using-jquery) – James G. Apr 22 '15 at 22:38
  • You're looking to cancel the ajax request itself, not the JSON that it returns. – James G. Apr 22 '15 at 22:39
  • Thanks, but it's not about how to stop an ajax request. It's about how to notify the pulling procedure in proper way. – Rom098 Apr 22 '15 at 22:40
  • Oh I see. Yeah, Arthur has the right answer then. – James G. Apr 22 '15 at 22:42
  • @Rom098 _"The problem is I have no idea how to stop pulling jsons on Cancel click."_ Not certain interpret requirement correctly ? If `.ajax()` returns `error` , call `$.ajax()` again , until `success` calls `$('div#waitdialog').dialog('close');` ? , with ability to call `$('div#waitdialog').dialog('close');` by button `click` from outside of `waitForResponse()` recursive calls ? – guest271314 Apr 22 '15 at 22:52

2 Answers2

0

You have to clear your timeout, look the new timeout_id variable

var timeout_id;
function waitForResponse () {
    // pull jsons until it's ok
    $.ajax({
        url: ...,
        dataType: 'json'
    }).done(function (rsp, status) {
        // OK. Close the wait dialog.
        $('div#waitdialog').dialog('close');
    }).fail(function (rspobj, status, msg) {
        // Not yet. Pull it again.
        timeout_id = setTimeout(waitForResponse, 3000);
    });
}

$('<div id="waitdialog">')
    .appendTo('body')
    .append(spinner())
    .dialog({
        buttons: {
            Cancel: function () {
                $(this).dialog("close");
                clearTimeout(timeout_id);
            }
        },
        close: function (event, ui) {
            $(this).remove();
        }
    });

waitForResponse();
Arthur
  • 4,870
  • 3
  • 32
  • 57
  • For a little code like that yes... Your waitForResponse is set on global too. Adapt the concept to your code – Arthur Apr 22 '15 at 22:45
  • doesn't have to be global, can set it in higher level scope that has access to function, even in a ready handler – charlietfl Apr 22 '15 at 23:01
  • BTW your solution doesn't take into account that Cancel event may occur after AJAX request was sent, but before timeout is set. – Rom098 Apr 23 '15 at 13:51
  • yes it is. You can click on cancel when you want and the ajax will not be called anymore. – Arthur Apr 23 '15 at 14:15
0

Found the following solution w/o global variables - just check if the dialog exists on the page.

function waitForResponse () {
    if (0 === $('div#waitdialog').length) {
        // Looks like User canceled it.
        return;
    }
    // pull jsons until it's ok
    $.ajax({
        url: ...,
        dataType: 'json'
    }).done(function (rsp, status) {
        // OK. Close the wait dialog.
        $('div#waitdialog').dialog('close');
    }).fail(function (rspobj, status, msg) {
        if (0 !== $('div#waitdialog').length) {
            // Not yet. Pull it again.
            setTimeout(waitForResponse, 3000);
        }
    });
}

$('<div id="waitdialog">')
    .appendTo('body')
    .append(spinner())
    .dialog({
        buttons: {
            Cancel: function () {
                $(this).dialog("close");
            }
        },
        close: function (event, ui) {
            $(this).remove();
        }
    });

waitForResponse();
Rom098
  • 2,445
  • 4
  • 35
  • 52
  • You're using a trick to get your goal. And you don't want use global variable, but I think your jQuery DOM analyse to know how many `div#waitdialog` they is on the page is heavier. – Arthur Apr 23 '15 at 13:45
  • @Arthur, I guess there is some kind of cache inside jQuery, moreover doing so once per 3 seconds is not so heavy. – Rom098 Apr 23 '15 at 13:49
  • @Arthur And yes, in some other cases I'd use a global variable (as I wrote in the question) - I'd use a flag indicating that an user canceled the request, and I'd use the flag checking instead of "0 === $('div#waitdialog').length". – Rom098 Apr 23 '15 at 13:56