Насколько безопасны скрытые запросы AJAX, которые имитируют производительность?

48

Что такое скрытый запрос AJAX?

Я заметил увеличение использования скрытых запросов AJAX, предназначенных для немедленного выполнения действий пользователя. Я буду называть этот тип запроса AJAX неблокирующим. Это AJAX-запрос, выполненный без уведомления пользователя, что он выполняется, он выполняется в фоновом режиме и работает тихо ( нет подробного указания на успешное завершение вызова AJAX ). Цель состоит в том, чтобы заставить операцию казаться, что она произошла немедленно, когда она действительно не закончена.

Вот примеры неблокирующего AJAX-запроса;

  • Пользователь нажимает удалить коллекцию писем. Элементы немедленно исчезают из папки «Входящие» и могут продолжать другие операции. Тем временем AJAX-запрос обрабатывает удаление элементов в фоновом режиме.
  • Пользователь заполняет форму для новых записей. Клики сохранить. Новый элемент появляется в списке немедленно. Пользователь может продолжать добавлять новые записи.

Чтобы уточнить, вот примеры блокирования AJAX-запроса;

  • Пользователь нажимает удалить коллекцию писем. Появится курсор с песочными часами. Запрос AJAX сделан, и когда он отвечает, курсор песочных часов выключен. Пользователь должен подождать секунду для завершения операции.
  • Пользователь заполняет форму для новых записей. Клики сохранить. Форма становится серой с анимацией загрузчика AJAX. Появится сообщение «Ваши данные были сохранены», и новая запись появится в списке.

Разница между двумя вышеупомянутыми сценариями состоит в том, что неблокирующая настройка AJAX не обеспечивает обратную связь о выполнении операции, а блокирующая настройка AJAX делает.

Риск скрытых запросов AJAX

Самый большой риск этого стиля запроса AJAX заключается в том, что веб-приложение может находиться в совершенно другом состоянии при сбое запроса AJAX.

Например, неблокирующий пример;

  • Пользователь выбирает кучу писем. Нажимает кнопку удаления. Похоже, операция происходит немедленно (элементы просто исчезают из списка). Затем пользователь нажимает кнопку «Создать» и начинает вводить новое письмо. В это время код JavaScript обнаруживает сбой запроса AJAX. Скрипт может показывать сообщение об ошибке, но на самом деле это бессмысленно.

Альтернативно, пример блокировки;

  • Пользователь выбирает кучу писем. Нажимает кнопку удаления. Видит песочные часы, но операция не удается. Они получают сообщение об ошибке «ошибка. Бла-бла-бла». Они возвращаются обратно в список электронных писем, и у них все еще есть письма, которые они хотели удалить. Они могут попытаться удалить их снова.

Существуют и другие технические риски для выполнения неблокирующих запросов AJAX. Пользователь может закрыть браузер, может перейти на другой веб-сайт, и он может перейти в другое место в текущей сети, что делает контекст любого сообщения об ошибке бессмысленным.

Так почему же это так популярно?

Facebook, Google, Microsoft и т. Д. И т. Д. - все эти большие домены все чаще используют неблокирующие AJAX-запросы, чтобы заставить операции казаться, что они выполняются мгновенно. Я также видел увеличение количества редакторов форм, у которых нет кнопки сохранения или отправки . Как только вы покидаете поле или нажимаете ввод. Значение сохранено. Нет в вашем профиле обновленного сообщения или шага сохранения.

Запросы AJAX не являются достоверными и не должны рассматриваться как успешные до тех пор, пока они не будут выполнены, но многие крупные веб-приложения работают именно так.

Эти веб-сайты, которые используют неблокирующие вызовы AJAX для имитации реагирующих приложений, несут ненужный риск за счет быстрого появления?

Это шаблон дизайна, которому мы все должны следовать, чтобы оставаться конкурентоспособными?

Reactgular
источник
20
Это оправдано тем фактом, что успешная работа гораздо более вероятна, поэтому медленная работа, чтобы избежать редкого случая чрезмерно оптимистичной обратной связи, является плохим компромиссом. Переместившись на личные отношения, вы бы предпочли взаимодействовать со спокойным, солнечным человеком или человеком, который категорически полагает, что все, что может пойти не так, пойдет не так и будет действовать соответственно?
Килиан Фот
1
Для меня то, с чем я борюсь, это то, что в настольном приложении и операция, и ошибка происходят немедленно. Где, как, с веб-приложениями операция происходит немедленно, но ошибка отстает. Тем не менее, сайты работают с дизайном настольного приложения.
Reactgular
7
Рассматривали ли вы также, что происходит, когда ваше настольное приложение записывает на диск, оно на самом деле помещается в буфер ОС, и происходит сбой диска до того, как он может быть записан на диск? Или, в этом отношении, диск отказывает после того, как байты записаны на диск. В обоих случаях пользователь думает , что что-то произошло, когда это действительно не произошло.
kdgregory
2
@KilianFoth Я бы предпочел того, кто предполагает, что все может пойти не так, если «солнечный» человек собирается ударить вас и украсть ваш кошелек при первых признаках неприятностей. Так что это зависит от масштаба реакции страницы на провал.
Изката
1
@ButtleButkus Я думаю, что эти сообщения сохранения являются новыми. Их не было, когда я задал вопрос. Я заметил, что Google добавляет больше отзывов в последнее время, что он делает вещи в фоновом режиме.
Reactgular

Ответы:

62

Это не столько «поддельная» производительность, сколько реальная отзывчивость. Есть несколько причин, почему он популярен:

  • В настоящее время интернет-соединения достаточно надежны. Риск сбоя AJAX-запроса очень низок.
  • Выполняемые операции не являются критически важными для безопасности. Если ваши электронные письма не удаляются на сервере, самое худшее, что происходит, это то, что вы должны удалить их снова при следующем посещении страницы.
  • Вы можете создать свою страницу так, чтобы она отменяла действие, если запрос не удался, но вам не обязательно быть таким тонким, потому что это означает, что ваше соединение с сервером разорвано. Проще сказать: «Соединение потеряно. Не удалось сохранить последние изменения. Повторите попытку позже».
  • Вы можете настроить свою страницу так, чтобы она разрешала только один ожидающий AJAX-запрос, поэтому ваше состояние не будет слишком синхронизировано с сервером.
  • Браузер предупреждает вас, если вы пытаетесь закрыть или отойти от страницы, пока AJAX-запрос находится на рассмотрении.

AJAX в ожидании предупреждения

Карл Билефельдт
источник
8
Последний пункт, все ли браузеры делают это по умолчанию?
Свиш
Я не знаю. Я тестировал только на IE9 и последней версии Chrome.
Карл Билефельдт
3
Вы, очевидно, не знакомы с австралийским интернетом, не говоря уже о бедных, развивающихся и изолированных местах, даже мобильных на движущемся транспортном средстве ...
hippietrail
2
@hippietrail Ну, ты не можешь сделать всех счастливыми все время.
КОВИКО
1
Когда пользователь отправляет запрос, он не всегда запрашивает новую страницу. Я думаю, что хорошо разработанные приложения AJAX могут сделать их более приятными, позволяя пользователю узнать, что происходит более эффективно, чем с перезагрузкой.
Frederik.L
32

Предполагать, что что-то будет работать, и отображать ошибку в случае сбоя на удаленной стороне гораздо удобнее для пользователя, чем блокировать выполнение пользователем чего-либо еще до получения ответа от сервера.

Почтовый клиент на самом деле является отличным примером для этого: когда у меня есть список с 5 электронными письмами и выбран верхний, я ожидаю, что при DELтрехкратном нажатии первые три электронных письма будут удалены. С «неблокирующим AJAX» это работает нормально - каждый раз, когда я нажимаю клавишу, выбранное письмо немедленно удаляется. Если что-то идет не так, отображается сообщение об ошибке и либо снова отображаются неправильно удаленные электронные письма, либо страница перезагружается, чтобы избавиться от несовместимого локального состояния.

Так что в наиболее распространенном случае - это успех - это улучшает удобство использования. В редком случае - сбой - удобство использования ухудшается (удаленный элемент появляется снова или приложение «перезапускается»), но при создании приложения вы обычно хотите добиться наилучшего удобства использования в обычных случаях, а не в случае ошибок.

ThiefMaster
источник
1
+1 это место в глубине души. По умолчанию в настоящее время люди реализуют настолько большую безопасность, что в худшем случае вы все еще не рискуете совершить ошибки пользователя: представьте, что почтовый клиент не удаляется, теперь локальное состояние плохое, и они пытаются удалить электронную почту 4, которая выровнена неправильно с сервером подавляющее большинство внутренних разработчиков получит безопасную ловушку, гарантирующую, что вы удаляете только то, что абсолютно хочет пользователь, и поэтому такое смещение не приведет к ошибочному удалению (может произойти сбой по ошибке, но не удалит) ,
Джимми Хоффа
@JimmyHoffa вы бы использовали уникальный идентификатор электронной почты в запросе на удаление. Было бы очень плохо отправлять запросы на удаление в зависимости от произвольного порядка отображения электронных писем в вашем почтовом ящике.
Баттл Буткус
14

Пользователям не важно, что ваша программа делает за кулисами: они хотят, чтобы их действия имели видимый эффект и могли работать в своем темпе.

Если действие было успешным на стороне клиента - например, удаление электронной почты - ваша задача - сделать его успешным и на стороне сервера. Почему удаление не удалось? Если это связано с какими-то ограничениями (например, вы не можете удалить сообщение, которое было заархивировано), пользователь должен знать об этом до того, как его действие не будет выполнено.

Если ошибка вызвана чем-то более серьезным (например, сбой базы данных), у вас должен быть способ сохранить операцию и повторить попытку, когда система снова заработает.

Хорошим примером такого управления является то, как Facebook управляет чатом. Нет никакого способа остановить внезапное отключение пользователя, а это значит, что он не сможет прочитать сообщения, которые вы отправили, прежде чем они уйдут. Вместо отображения ошибки система сохраняет все эти сообщения и делает их доступными пользователю, когда он возвращается. Данные не потеряны.

DistantEcho
источник
2
+1. Отличный пример чата. Большинство пользователей ожидают, что их сообщение будет немедленно сделано доступным для всех, и, поскольку такие сообщения редко дают сбой, пользователям создается иллюзия, что это именно так.
Нил
1
@Niphra, "Почему удаление не удалось?" Сеть может выйти из строя по многим причинам, ни одна из которых не связана с вашим приложением. Там нет ничего вы можете сделать , чтобы остановить это.
Pacerier
5

Вы можете пойти на компромисс между двумя вариантами. Например, если пользователь удаляет сообщение электронной почты, вы можете пометить его красным или серым, пока не получите подтверждение от сервера, и только затем удалить его из списка. Пользователь по-прежнему может выполнять другие действия, пока одно действие находится в состоянии ожидания, поэтому оно не блокируется, но все равно оставляет для пользователя небольшое напоминание о том, что его действия еще не были совершены.

Amazon AWS использует такой подход: когда вы останавливаете / запускаете экземпляр, флажок, который позволяет вам выбрать его, превращается в счетчик (так что вы ничего не можете с ним сделать в течение нескольких секунд), но это не блокирует вас от взаимодействовать с другими экземплярами.

VALTRON
источник
Ваше предложение аналогично тому, как в gmail отображается текст "Сохранение ..." во время работы XHR, и "Сохранение" после его завершения. Если бы он всегда говорил «Спасен», кто бы поверил в это?
Баттл Буткус
3

Я думаю, это связано с тем, что все больше и больше веб-сайтов пытаются вести себя как приложения и выполнять больше операций в браузере (например, проверять данные формы), чем более традиционные сайты. Я не вижу в этом особой проблемы, если ваш код надежен и вы можете ожидать, что он будет успешным в нормальных условиях.

Вы говорите: «В это время код JavaScript обнаруживает сбой запроса AJAX. В сценарии может отображаться сообщение об ошибке, но в настоящий момент это бессмысленно».

Почему это должно быть бессмысленно? Вы можете вернуться в список сообщений электронной почты и снова выполнить удаление. Зачем ждать вместо этого? На самом деле нет большого «риска», и они не «кажутся» быстрыми, они на самом деле работают быстрее. Так что, если активность не является «критической», зачем медлить?

Торстен Мюллер
источник
1
Возможно, бессмысленное слово было неправильным, но я имею в виду, что в сообщении об ошибке отсутствует относительный контекст, потому что пользователь теперь делает что-то совершенно другое. Я пытаюсь сказать, что невежественному пользователю сети они думали, что электронные письма действительно удаляются. Так почему теперь, позже, они получают сообщение об ошибке за то, что они «видели» были удалены. Для нас, программистов, мы понимаем, но для дедушки, использующего gmail, они не поймут.
Reactgular
Большинство людей предпочли бы использовать приложение, где все происходит немедленно, система реагирует, и есть вероятность того, что пользовательский интерфейс может странным образом обновить ошибку при ошибке 1: 100, чем приложение, которое зависает на одну секунду каждый раз, когда они изменяют значение.
Gort Робот
1

Мой 2c: есть ситуации, когда лучше иметь, как вы говорите, «неблокирующие» Ajax-операции и другие, когда это плохой выбор дизайна. Пример: голосование на видео YouTube. Вы действительно не хотите, чтобы какая-либо часть страницы была заблокирована, пока вы нажимаете на маленькое начало там. Лучше молча провалиться. Даже сообщение с подтверждением будет чрезмерным. Однако ваш пример с удалением электронной почты я бы назвал обязательным для Ajax-запроса блокирующего типа.

Mongo DB делает что-то подобное (и это можно рассматривать как пример настольного приложения). Они имеют различные «Записать проблемы» для своих операций, и вы можете настроить его на разные значения для каждой операции, начиная от «вернуться сразу и ничего не ждать» до «блокировать», пока не получите подтверждение успешной передачи по сети и затем вернитесь «к», чтобы дождаться правильного планирования содержимого для записи на диск на удаленной машине перед вашим возвратом ». Очевидно, что если вы сделаете толстый клиент Desktop (например, C ++) с помощью драйвера Mongo, вы установите наименьшую заботу о записи для операций с минимальными «критичностью» для операций с БД (таких как проверка новой электронной почты) и других для более жестких задач записи. ,

Хотя я вижу полезность неблокирующего Ajax, я согласен с вами, что это происходит слишком часто. В какой-то момент был хотя бы один известный сайт «социальной сети», который делал бы это для загрузки фотографий. Вы бы выбрали свою фотографию для загрузки, а затем bam, сразу же она скажет вам, что она сделана, и затем достаточно уверена, что на следующий день, когда вы захотите добавить еще несколько фотографий (или использовать то, что, как вы думали, уже добавили), оно никогда не был найден. Позже они отказались от этого и фактически нашли время, чтобы дождаться ответа (и вы действительно иногда получали сообщения типа «не удалось загрузить фотографию, попробуйте позже»).

Дракон Шиван
источник
+1 за то, что вижу вещи по-своему :). Загрузка фотографий является отличным примером неудачной загрузки.
Reactgular
1
Почему блокирующая загрузка предпочтительнее? В Picasa (веб-интерфейс) вы можете перетаскивать фотографии, а пока они загружаются в фоновом режиме, вы можете перетаскивать больше или отмечать фотографии, которые закончили, и т. Д. Операция блокировки загрузки может привести к ужасному UX
BLSully