【问题标题】:Show element only if getJSON takes more than n milliseconds?仅当 getJSON 花费超过 n 毫秒时才显示元素?
【发布时间】:2013-08-11 10:51:45
【问题描述】:

我有一些 JavaScript:

surveyBusy.show();

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

但是,如果$.getJSON 花费的时间超过n 毫秒数,我只想发出surveyBusy.show();。否则你会闪烁。 getJSON api 上是否有回调可以做到这一点?我看到nothing in the documentation

【问题讨论】:

  • 我刚刚发布了一个答案,它为您提供了 AJAX API 中提供的回调来执行此操作而无需额外的代码。

标签: javascript jquery html ajax


【解决方案1】:

实际上,根据this page, which describes the callbacks for all AJAX routines, 有一个超时回调可以使用。它要求您不要使用$.getJSON 快捷方式。因此,要为这个问题提供真正的答案,是的,它在 API 中,但比 $.getJSON 快捷方式更深。

timeout 类型:Number 设置请求的超时时间(以毫秒为单位)。这将覆盖使用 $.ajaxSetup() 设置的任何全局超时。 超时时间从 $.ajax 调用开始;如果 其他几个请求正在进行中,浏览器没有 连接可用,请求可能在之前超时 它可以发送。在 jQuery 1.4.x 及更低版本中,XMLHttpRequest 对象 如果请求超时,将处于无效状态;访问任何 对象成员可能会抛出异常。仅在 Firefox 3.0+ 中,脚本 并且 JSONP 请求不能被超时取消;脚本将 即使在超时时间之后到达也运行。

【讨论】:

  • 也许展示一个将他们的$.getJSON 调用转换为$.ajax 的示例(应该不多),所以他们可以利用timeout
  • 虽然我很确定如果超时,fail 回调被执行,这可能是不希望的
  • “相当肯定”和“可能”听起来只是试图使我的答案无效的理由,而不是有根据的评论。
  • The Solution 要求提供与 API 相关的答案,而不是代码 sn-p,这正是我提供的。
  • 不幸的是,他们询问了 API 回调,所以如果你想成为技术专家,你的答案是无关紧要的。就像我说的,如果你费心提供一个例子并测试它,你会发现它的含义。抱歉,我不想自己测试,这不是我的答案
【解决方案2】:

这将在surveyBusy 对象中设置一个方法,从而避免在window 对象下创建setTimeout 方法。它为您提供了更多可重复使用的东西!

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);
    });

【讨论】:

  • 我必须尝试一下,但我很确定这不会起作用,因为 always 直到 得到响应后才会执行。
  • @TheSolution 这不是 OP 要求的吗?它必须至少花费“n”秒,否则.show() 不会发生。还是我看错了?
【解决方案3】:

如果在激活之前返回结果,请将您的 surveyBusy.show() 调用置于超时内,然后取消该超时(使用 window.clearTimeout):

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();        
    });

【讨论】:

    【解决方案4】:

    尝试设置超时,然后在服务器响应时取消它:

    // 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】:

      使用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();
          });
      

      【讨论】:

        【解决方案6】:
        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();
            });
        

        【讨论】:

          【解决方案7】:

          只需使用超时。另外,我将您的“隐藏”代码放在 always 处理程序中以减少代码重复。

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

          【讨论】:

          • 4 个建议的最佳解决方案,几乎相同
          • 我建议的一个改进是在调用setTimeoutclearTimeout 方法时引用window 对象。除此之外,+1。
          • @rink.attendant.6 为什么会这样?
          • @Ian 表示您要使用的方法是附加到 window 对象的方法,以防 setTimeoutclearTimeout 在全局命名空间中的其他位置被重新定义,这可能是故意的,也可能不是故意的。
          • @rink.attendant.6 没有理由用window. 前缀污染你的代码。你在任何地方都使用window. 吗?你在用window.document.whateverMethod吗?或者对于您创建的每个全局变量/函数?我希望不会,这对于暗示的东西来说有点过分了。如果它在全局命名空间的其他地方被重新定义,就没有办法解决这个问题——添加window. 并不能神奇地找到原来的......它已经被覆盖了
          猜你喜欢
          • 2023-03-09
          • 2018-09-03
          • 1970-01-01
          • 2021-06-13
          • 1970-01-01
          • 2022-06-17
          • 1970-01-01
          • 2016-06-02
          • 2023-04-09
          相关资源
          最近更新 更多