【问题标题】:Cancel "done" listener to jQuery AJAX Deferred?取消 jQuery AJAX Deferred 的“完成”侦听器?
【发布时间】:2016-06-27 13:46:47
【问题描述】:

如果我有一个通过 jQuery $.ajax() 调用发起的 AJAX 请求,并且当时附加了一个 done() 监听器,有没有办法取消监听它?我有一个“即用型搜索”字段的情况,如果向服务器发出请求,无论出于何种原因需要很长时间才能响应,但是在等待用户输入更多内容时,会触发第二个请求并很快回来,当第一个请求最终完成时,done() 监听器触发,用第一个请求的数据重写 DOM,而不是第二个。

我尝试在发出第二个请求之前在 AJAX 上发出 abort() 调用,或在 Deferred 上发出 reject(),但这显示了第一个调用的错误状态,而第二个调用正在进行中.

我尝试提出一个 ID 系统来散列哪个请求是“当前”请求,因此在 done() 侦听器中它首先检查“我仍然是最近的请求吗?”在更新 DOM 之前,但应用程序需要为每个 API 端点创建 ID/Hash 方法似乎很笨重?

【问题讨论】:

    标签: ajax jquery-deferred


    【解决方案1】:

    在每个完成的回调中,您可以记录一个时间戳,并且仅当时间戳是最新的时才执行回调。所以:

    var latest_ts = 0;
    $.get('...').done(function() {
        var this_ts = (new Date).getTime();
        if (this_ts < latest_ts) return;
        latest_ts = this_ts;
        //callback code here...
    });
    

    因此,如果请求 A 被触发,但请求 B 在它之后触发但首先返回,则时间戳会更新并且 A 的回调将被忽略,因为它的时间戳已过期。

    【讨论】:

    • 确实;我已经在这样做了,因此不会在每次按键时都触发请求。问题是广泛的搜索(例如“e”)会返回很多结果(并且需要一段时间),而更具体的搜索(例如“ear”)只会返回一些结果(并且可能会返回更快)。
    • 嗯,有趣的想法,但不是那种特定的逻辑;您在done() 处理程序中发生了(new Date).getTime(),它仅在请求解决时触发,并且它们解析的顺序始终是它们解析的顺序,因此时间戳永远不会乱序。将时间戳标记在与$.get()相同的级别(标记您开始请求的时间,而不是结束时间)与为请求设置ID相同;当它解析时,它需要知道它是哪个 ID(时间戳),以了解它是否改变了。
    猜你喜欢
    • 1970-01-01
    • 2011-09-26
    • 2020-01-24
    • 2017-08-08
    • 1970-01-01
    • 2021-12-20
    • 1970-01-01
    • 1970-01-01
    • 2013-04-23
    相关资源
    最近更新 更多