Как вы отменяете долгосрочную клиентскую сторону действия MVC AJAX (в javascript)? - PullRequest
10 голосов
/ 18 января 2012

У меня длительное (4-10 секунд) MVC-действие, которое запускает отчет из вызова AJAX. Пока он работает, пользователи могут изменять параметры и запускать что-то еще, поэтому я отменяю запрос AJAX, прежде чем сделать другой.

Так, например (например, в jQuery, но проблема возникает независимо):

// If we have an active request and it's not complete
if(dataRequest && dataRequest.readyState != 'complete') 
{
    dataRequest.abort();
}

dataRequest = $.ajax(...);

На стороне клиента это работает нормально, но отмененный запрос все еще выполняется на сервере. Например, если отчет занимает 10 секунд, а я отменяю один и запускаю другой, второй запрос занимает 20 секунд.

Я думаю, это связано с блокировкой уровня сеанса :

[Если] для одного и того же сеанса делается два одновременных запроса (с использованием то же значение SessionID), первый запрос получает эксклюзивный доступ к информация о сеансе. Второй запрос выполняется только после Первый запрос завершен.

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

Можно ли остановить одно действие и начать следующее без использования AsyncController или [SessionState(SessionStateBehavior.ReadOnly)]?

Если это не так, оба требуются?

Ответы [ 3 ]

4 голосов
/ 31 января 2012

Как оказалось, для полного ответа потребовались две вещи:

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

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

Это доступно как свойство ответа : this.Response.IsClientConnected

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

4 голосов
/ 18 января 2012

[SessionState(SessionStateBehavior.ReadOnly)] или полного отключения сеанса достаточно, чтобы разрешить одновременный доступ к действиям контроллера из одного сеанса. Таким образом, второй запрос (из того же сеанса) не должен ждать завершения первого до обработки. Что касается отмены первого действия на сервере, то это будет сложнее. Вам нужно будет связать каждую задачу с уникальным идентификатором, и когда новая задача будет запущена, верните этот идентификатор задачи клиенту. Затем, когда вы отменяете запрос AJAX на клиенте, вызывая .abort(), вы можете запустить другой запрос AJAX для какого-либо другого действия контроллера и передать ему уникальный идентификатор задачи. Это действие контроллера само по себе установит некоторый общий флаг для указания первого действия, которое нужно остановить.

TPL имеет встроенную поддержку отмены, которую вы можете посмотреть, чтобы упростить ее, чтобы избежать общей структуры данных между двумя, которая будет их синхронизировать.

1 голос
/ 29 февраля 2012

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...