Show element only if getJSON takes more than n mil

2020-08-13 06:34发布

问题:

I have some JavaScript:

surveyBusy.show();

$.getJSON(apiUrl + '/' + id)
    .done(function (data) {
        ...
        surveyBusy.hide();
    })
    .fail(function (jqXHR, textStatus, err) {
        ...
        surveyBusy.hide();
    });

However, I'd like to only issue surveyBusy.show(); if $.getJSON takes more than n number of milliseconds. You get a flicker otherwise. Is there a callback on the getJSON api that can do this? I see nothing in the documentation.

回答1:

Just use a timeout. Also, I put your "hide" code in the always handler to reduce code repetition.

var busyTimeout = setTimeout(function() { surveyBusy.show(); }, 2000);

$.getJSON(apiUrl + '/' + id)
    .done(function (data) {
        ...
    })
    .fail(function (jqXHR, textStatus, err) {
        ...
    })
    .always(function() {
        clearTimeout(busyTimeout);        
        surveyBusy.hide();        
    });


回答2:

Put your surveyBusy.show() call inside a timeout and then cancel that timeout (using window.clearTimeout) if the result is returned before it activates:

var busyTimeout = window.setTimeout(function() { surveyBusy.show(); }, 500);

$.getJSON(apiUrl + '/' + id)
    .done(function (data) {
        ...
    })
    .fail(function (jqXHR, textStatus, err) {
        ...
    })
    .always(function() {
        window.clearTimeout(busyTimeout);        
        surveyBusy.hide();        
    });


回答3:

Use setTimeout:

var busy = window.setTimeout(function(){
    surveyBusy.show();
}, 1000);

$.getJSON(apiUrl + '/' + id)
    .done(function (data) {
        // ...
        window.clearTimeout(busy);
        surveyBusy.hide();
    })
    .fail(function (jqXHR, textStatus, err) {
        // ...
        window.clearTimeout(busy);
        surveyBusy.hide();
    });


回答4:

Try this setting a timeout, then canceling it when the server responds:

// NOT TESTED

var n = 5000 // milliseconds
var tmr = setTimeout(function(){
    surveyBusy.show();
}, n);

$.getJSON(apiUrl + '/' + id)
    .done(function (data) {
        ...
        clearTimeout(tmr) ;
        surveyBusy.hide();
    })
    .fail(function (jqXHR, textStatus, err) {
        ...
        clearTimeout(tmr) ;
        surveyBusy.hide();
    });


回答5:

This will set up a method within the surveyBusy object that will avoid having to create a setTimeout method under the window object. It gives you something a lot more reusable!!

surveyBusy = {
    onTimer: function(n) {
        elapsed = new Date.getTime() - start;
        if (elapsed > n) surveyBusy.show();
    }
}
surveyBusy.hide();
var start = new Date().getTime();
var elapsed = 0;

$.getJSON(apiUrl + '/' + id)
    .done(function (data) {
        ...
    })
    .fail(function (jqXHR, textStatus, err) {
        ...
    })
    .always(function() {
        surveyBusy.onTimer(5000);
    });


回答6:

Actually, according to this page, which describes the callbacks for all AJAX routines, there is a timeout callback that you can use. It will require that you don't use the $.getJSON shortcut. So, to provide a REAL answer to the question, YES it is in the API but buried deeper than the $.getJSON shortcut.

timeout Type: Number Set a timeout (in milliseconds) for the request. This will override any global timeout set with $.ajaxSetup(). The timeout period starts at the point the $.ajax call is made; if several other requests are in progress and the browser has no connections available, it is possible for a request to time out before it can be sent. In jQuery 1.4.x and below, the XMLHttpRequest object will be in an invalid state if the request times out; accessing any object members may throw an exception. In Firefox 3.0+ only, script and JSONP requests cannot be cancelled by a timeout; the script will run even if it arrives after the timeout period.



回答7:

var n = 1000; //number of ms to wait
var done = false;
window.setTimeout(function(){
    if(!done){
        surveyBusy.show();
    }
}, n);

$.getJSON(apiUrl + '/' + id)
    .done(function (data) {
        ...
        done = true;
        surveyBusy.hide();
    })
    .fail(function (jqXHR, textStatus, err) {
        ...
                done = true;
        surveyBusy.hide();
    });