Прервать запрос JSONP ajax с помощью jQuery - PullRequest
16 голосов
/ 24 июня 2011

Я использую ajax-вызов JSONP для загрузки некоторого контента из другого домена, и все это выполняется, если пользователь вызывает «наведение мыши» на кнопке.

Я могу захватить $.Вызов ajax () возвращает как объект xhr и использует его для прерывания запроса ajax каждый раз, когда пользователь вызывает «наведение мыши».Но функция обратного вызова JSONP по-прежнему вызывается, и это вызывает ошибку, и я думаю, что это потому, что метод xhr.abort () не препятствует вызову функции обратного вызова.

Я пытался окружитьВызов $ .ajax () с try {} catch (e) {}, но после того, как я вызываю метод xhr.abort (), ошибка продолжается.

Есть ли способ обработать это исключение?

Возбужденное исключение выглядит так (согласно Firebug): jQuery16102234208755205157_1308941669256 не является функцией

И внутренняя структура исключения выглядит следующим образом: jQuery161022342087552051516691 (8989) (6889). мои данные json из другого домена ....})

Ответы [ 5 ]

11 голосов
/ 03 апреля 2012

Основной ответ - просто тот, который дан здесь : Вы не можете 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() сделать это для нас, конечно.

1 голос
/ 06 декабря 2016

Не прерывать запрос

Просто сохраните где-нибудь объект jqXHR , возвращаемый $.ajax()

theJqXHR = $.ajax(....

Если пользователь отменяет запрос на ноль сохраненного объекта

// user canceled
theJqXHR = null;

Наконец, когда вы получите ответ (success callback), обратный вызов сравнит объект 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 самостоятельно.

1 голос
/ 14 июня 2012

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,
  ...
});
0 голосов
/ 16 июня 2014

Ответ Тревора Бернхэма довольно хороший, но вместо отслеживания количества запросов вам нужно просто сравнить запрос с параметром 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 будет либо удалена, либо еще один запрос.

0 голосов
/ 24 июня 2011

В jQuery 1.5 все API-интерфейсы Ajax имеют объект-оболочку вокруг собственных объектов XHR. Взгляните на:

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

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