【问题标题】:Abort JSONP ajax request with jQuery使用 jQuery 中止 JSONP ajax 请求
【发布时间】:2011-09-22 06:50:04
【问题描述】:

我正在使用 JSONP ajax 调用从不同的域加载一些内容,如果用户在按钮上引起“鼠标悬停”,所有这些内容都会执行。

我可以将 $.ajax() 调用返回捕获为 xhr 对象,并在每次用户导致“鼠标悬停”时中止 ajax 请求。但是JSONP回调函数仍然被调用,这会导致错误,我认为这是因为xhr.abort()方法并没有阻止回调函数被调用。

我尝试使用 try{}catch(e){} 包围 $.ajax() 调用,但在调用 xhr.abort() 方法后,错误仍然存​​在。

有没有办法处理这个异常?

引发的异常是这样的(根据 Firebug): jQuery16102234208755205157_1308941669256 不是函数

而异常的内部结构是这样的: jQuery16102234208755205157_1308941669256({...我来自不同域的json数据...})

【问题讨论】:

  • 我想这不是那么重复,因为这个问题是关于在 JSONP ajax 请求上调用 jqxhr.abort() 方法之后防止异常,而不是关于如何停止请求本身。
  • 这个问题的答案可以在重复问题stackoverflow.com/questions/9533848/…找到
  • 非常老的问题。今天偶然发现了同样的问题。我添加了我的贡献。我不知道我的答案是否值得被接受,但可以肯定的是,接受的答案不应该是当前(被否决的)答案

标签: jquery ajax callback jsonp abort


【解决方案1】:

基本的答案就是给定here:你不能真的abort() 一个JSONP 调用。所以真正的问题是,如何避免多余的回调调用和您看到的错误?

你不能在回调周围使用try...catch,因为它是异步的;您必须从 jQuery 的末尾捕获它,并且 jQuery 通常不处理回调引发的异常。 (我在我的书中讨论了这个问题,Async JavaScript。)您想要做的是为每个 Ajax 调用使用一个唯一标识符,并且在调用成功回调时,检查该标识符是否与您创建时的标识符相同通话。这是一个简单的实现:

var requestCount = 0;
$.ajax(url, {
  dataType: 'jsonp',
  requestCount: ++requestCount,
  success: function(response, code) {
    if (requestCount !== this.requestCount) return;
    // if we're still here, this is the latest request...
  }
});

这里我利用了这样一个事实,即您传递给$.ajax 的任何内容都附加到在回调中用作this 的对象。

当然,如果 jQuery 让 abort() 为我们做这件事就好了。

【讨论】:

    【解决方案2】:

    不要中止请求

    只需将$.ajax()返回的jqXHR对象存储在某处

    theJqXHR = $.ajax(....
    

    如果用户取消请求,则保存的对象为空

    // user canceled
    theJqXHR = null;
    

    最后,当您收到响应(success 回调)时,回调会将响应的 jqXHR 对象与保存的对象进行比较。

    function successCallback(data, textStatus, jqXHR )
    {
        if( theJqXHR !== jqXHR )
        {
            // user canceled; discard the response
            return;
        }
    
        // process the response
    }
    

    没有 jQuery 错误。


    一般建议不要依赖abort(),即使是常规的 ajax 请求。

    1. 在任何情况下,您都不会在服务器上节省资源,因为您发送的请求将被处理并且无法停止。并且会有回应。

    2. 一些(旧)浏览器无法正确处理abort()

    只需“缓存”jqXHR 对象并自己处理CANCEL 场景。

    【讨论】:

    • 第三个参数 XHR 从不匹配 $.ajax 返回的对象
    • @JackCole 我试过了,实际上是的,确实如此。在控制台上试试这个:jqxhr1=$.ajax({url: "/", success: function(data,status,jqxhr2){alert(jqxhr1===jqxhr2);}}) 我得到的是true
    【解决方案3】:

    jsonpString 覆盖 jsonp 请求中的回调函数名称。在“callback=?”中将使用该值代替“callback” URL 中查询字符串的一部分。

    所以{jsonp:'onJSONPLoad'} 将导致'onJSONPLoad=?' 传递给服务器。从 jQuery 1.5 开始,将 jsonp 选项设置为 false 可防止 jQuery 将 ?callback 字符串添加到 URL 或尝试使用 =? 进行转换。在这种情况下,您还应该明确设置jsonpCallback 设置。例如,{ jsonp: false, jsonpCallback: "callbackName" }

    http://api.jquery.com/jQuery.ajax/

    jQuery 添加?callback=jQuery17109492628197185695_1339420031913 并稍后将请求数据设置为此回调的参数,因此您将拥有:

    jQuery17109492628197185695_1339420031913({
      "status": 200,
      "data": {your json}
    })
    

    为避免设置额外的参数来请求URL和调用回调,将此参数添加到ajax方法:jsonp:false,所以它看起来像:

    $.ajax({
      ...
      jsonp:false,
      ...
    });
    

    【讨论】:

      【解决方案4】:

      Trevor Burnham 的回答非常好,但您应该只将请求与 XHR 参数进行比较,而不是跟踪请求计数,就像这样;

      doRequest: function() {
          this._freeRequest();
      
          this._request = $.getJSON(url + params + '&callback=?', function(response, status, xhr) {
              if (this._request !== xhr) return; // aborted
      
              // success
          }.bind(this)).done(this._freeRequest.bind(this));
      }
      
      _freeRequest: function() {
          if (this._request) {
              delete this._request;
          }
      }
      

      在前一个请求完成之前再次调用doRequest_freeRequest 一次,将导致if (this._request !== xhr) 行变为真,从而导致所述请求的“中止”,因为this._request 将被删除或完全是另一个请求。

      【讨论】:

        【解决方案5】:

        在 jQuery 1.5 中,所有 Ajax API 都有一个围绕原生 XHR 对象的包装器对象。看看:

        http://api.jquery.com/jQuery.ajax/#jqXHR

         jqxhr.abort(); // should be what you're looking for
        

        【讨论】:

        • 这是我现在使用的。这将中止 ajax 请求。但是这个 ajax 请求使用 JSONP。在我使用“abort()”方法之后,调用了一个由 jQuery 内部生成的用于处理 JSONP 响应的 javascript 函数,但是 abort 方法似乎删除了该函数定义,或者什么,因为有一个我没有的异常能够应付。
        • 您还有更多信息吗?现场示例,异常消息?
        猜你喜欢
        • 2013-03-28
        • 2011-07-11
        • 2012-07-29
        • 2017-02-06
        • 2018-03-20
        相关资源
        最近更新 更多