Что произойдет, если ответ не получен для запроса? Я вижу повторы
Вопрос, который у меня есть, скорее всего связан с вопросом, связанным с браузером, который я думаю, но его довольно фундаментальным я тоже хотел бы найти ответ, поскольку я начинаю создавать веб-приложение.
В моем клиентском коде я делаю вызов $.ajax
. Это сообщение может занять некоторое время, чтобы ответить. То, что я вижу, - через некоторое время, когда запрос отправляется снова.
Я думал, что это мой вызов $.ajax
, отправляющий его снова, но независимо от того, сколько раз я вижу запрос POST на сервере, я вижу только обратный вызов beforeSend
, вызываемый один раз. Я уверен, что мой код не отправляет его более одного раза, поэтому я думаю, что его браузер повторяет?
Я знаю, что мой сервер получает запрос более одного раза, когда я запустил Wireshark и могу видеть пост-запрос несколько раз. Итак, мое предположение заключается в том, что это связано с HTTP? I.e., если ответ не получен в течение определенного промежутка времени, тогда запрос будет повторно отправлен?
Вот пример моего вызова ниже.
$.ajax({
async: false,
type: 'POST',
url: '<%= url_for('importDevice') %>',
data: { device: val },
retryLimit: 0,
//callback
success: function(data) {
alert('calling import');
if ( data == 'nomaster')
{
// Display a warning toast, with a title
toastr.warning('You must set the Master Key first!', 'Warning');
$.ismasterset = false;
//reset the form contents after added
} else
{
$("div#content").html(data);
}
},
beforeSend: function(){
alert('in before send');
}
});
Это все релевантный код, "retryLimit" не используется, я просто не удалял его из своего кода, и да, проблема была там до того, как я его ввел.
СОЕДИНЕНЬ с выходом от клиента и сервера.
ok Я установил "Live Http headers для Firefox".
На вкладке "Генератор" я вижу один единственный вызов
'#request# POST http://testhost/importdevice'
Я не вижу POST
в разделе "заголовки", может быть, потому что нет ответа?
На моем веб-сервере, хотя я вижу, что 2 вызова примерно на 22 секунды.
[Sun Jan 13 03:08:45 2013] [debug] POST /importdevice (Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:17.0) Gecko/20100101 Firefox/17.0).
[Sun Jan 13 03:09:07 2013] [debug] POST /importdevice (Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:17.0) Gecko/20100101 Firefox/17.0).
Я также вижу эти же вызовы в wirehark...
Вот почему я спрашивал, является ли это нормальным поведением, чтобы попытаться отправить запрос повторно, если ответ не вернется, аналогично рукопожатию TCP и ретрансляции SYN
.
НОВОЕ ОБНОВЛЕНИЕ
Кажется, это не имеет никакого отношения к моему звонку Ajax. Если я создаю кнопку с простым HREF.
то есть
<a href="/importdevice?device=serverA" class="btn btn-success">TestDirect</a>
Затем в моем "Live HTTP headers output" я получаю... только один экземпляр.
#request# GET http://172.16.118.15/importdevice?device=serverA
Но еще раз в моих журналах сервера я получаю.
[Sun Jan 13 03:20:25 2013] [debug] GET /importdevice (Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:17.0) Gecko/20100101 Firefox/17.0).
[Sun Jan 13 03:20:48 2013] [debug] GET /importdevice (Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:17.0) Gecko/20100101 Firefox/17.0).
И в wirehark на сервере я вижу его дважды... и, как и ожидалось, мой серверный код вызывается дважды... Это ДЕЙСТВИТЕЛЬНО запутывает меня.
Ответы
Ответ 1
Ознакомьтесь с этим сообщением в блоге, в котором объясняется, что происходит:
http://geek.starbean.net/?p=393
Согласно HTTP/1.1 RFC 8.2.4:
Если клиент HTTP/1.1 отправляет запрос, который включает тело запроса, но который не включает поле заголовка запроса Expect с ожиданием "100-продолжить", и если клиент напрямую не связан с HTTP/1.1, и если клиент видит, что соединение закрывается до получения какого-либо статуса с сервера, клиент ДОЛЖЕН повторить запрос.
Убедитесь, что вы создаете веб-приложение, чтобы терпеть эти дополнительные запросы. И если вы хотите, чтобы запрос ajax делал что-то только один раз, например, записывая что-то в базу данных, тогда вам нужно спроектировать запрос как idempotent. См.: Что такое идемпотентная операция?
Кроме того, это подчеркивает различия между операциями GET и POST:
http://www.cs.tut.fi/~jkorpela/forms/methods.html
Как общая проектная практика:
-GET-операции должны быть разработаны как idempotent
Операции -POST должны использоваться для записи в базы данных и т.д.
Ответ 2
Почему вы устанавливаете обратный вызов, если ваш запрос не асинхронный?
Если вы хотите, чтобы процесс синхронизации отправил код beforeSend перед вызовом и обратный вызов успех просто после вызова.
Если вы хотите использовать асинхронный подход, установите async: true
Также эта строка кода неверна:
url: '<%= url_for('importDevice') %>',
Посмотрите на цитаты: должно быть
url: '<%= url_for("importDevice") %>',
Возможно, эти предложения не решают проблему, но направят вас в правильном направлении. Проблема может быть где-то еще, чем в отправленном коде...
Возвращаясь к вашему вопросу:
Может быть, это браузер? Я не думаю, но кто знает, что там!... что за браузер? Вы пробовали с другим?
Я предлагаю попробовать с Firefox и использовать плагин Live httpHeaders (очень прост в настройке и использовании). Вы увидите, что происходит с клиентской стороны, чтобы увидеть, что происходит со стороны сервера.