Подтвердить что ты не робот

Отменить запрос ajax JSONP с помощью jQuery

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

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

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

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

Повышенное исключение выглядит следующим образом (согласно Firebug): jQuery16102234208755205157_1308941669256 не является функцией

И внутренняя структура исключения выглядит так: jQuery16102234208755205157_1308941669256 ({... мои данные json из другого домена....})

4b9b3361

Ответ 1

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

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

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

Ответ 2

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

Ответ 3

jsonpString переопределяет имя функции обратного вызова в запросе jsonp. Это значение будет использоваться вместо "обратного вызова" в "обратном вызове =?" часть строки запроса в 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

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

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

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 самостоятельно.

Ответ 5

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