Автосохранение с событием «unload» и вызовом ajax при выходе из системы: порядок действий вызывает проблему - PullRequest
9 голосов
/ 13 июня 2011

Я использую функцию автосохранения в онлайн-редакторе.

Когда пользователь покидает страницу (обнаруживается с помощью события unload или beforeunload), я отправляю запрос AJAX (async = false) для сохранения данных.

У меня проблема в Firefox et иногда в Chrome, потому что происходит серия событий:

  • событие сработало
  • запрос на отправку
  • страница меняется и пользователь отключается
  • запрос проанализирован сервером => проблема!
  • запрос ответа получен браузером

Конечно, поскольку пользователь был отключен, запрос "сохранить" не может быть обработан.

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

Ответы [ 5 ]

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

ori ответ правильный и полный.

Но, исходя из вашего случая, вы можете использовать обходной путь.

Существует две функции JavaScript, которые могут вас заинтересовать: localStorage и sessionStorage (этото же самое, за исключением того, что второй сбрасывается при закрытии браузера, поэтому вы, вероятно, выберете первый)

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

Код подтверждения концепции:

$(window).bind('unload', function() {
    localStorage.setItem('unsavedData',data);
    localStorage.setItem('unsaved',true);
});

$(document).ready(function(){
    if(localStorage.getItem('unsaved')){
       //ajax send 
       localStorage.setItem('unsaved',false);
    }
});

[edit]

Я успешно использую JSONP с unload, и, похоже, он работал большую часть времени, но я не тестировал его под нагрузкой и на медленнойсеть.

6 голосов
/ 12 января 2012

Нет.Вы можете только отобразить диалоговое окно подтверждения для пользователя:

$(window).bind('beforeunload', function() {
    // AJAX

    return 'STRING';
});

В диалоговом окне будет отображаться STRING, и тогда у вас может быть время для ответа, прежде чем пользователь отреагирует.

Но это единственный способ заблокировать выгрузку страницы, поэтому ответ ajax не будет получен.

0 голосов
/ 19 января 2012

Я использую onbeforeunload для чего-то похожего, но полезная нагрузка данных довольно мала (guid), и мне не нужно возвращаемое значение, так что оно срабатывает и забывается. Он работает примерно в 95% случаев, но разные браузеры по-разному реализуют функции preforeunload, onunload и т. Д.

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

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

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

Было бы проще сделать асинхронный режим ложным.

В противном случае вы можете вызвать сервер с помощью async: true, а когда он вернется либо успешно, либо с ошибкой, вы можете вызвать пользовательское событие для выхода из системы / перенаправления / ошибки.сообщение.

Для удержания пользователя в ожидании ответа сервера может использоваться зависающий прозрачный div.

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

А как насчет фиксированного прозрачного div в верхней части вашей страницы с событием hover для запуска сохранения? Просто думать с творческой точки зрения ... Сохраняйте сохранение, которое вы имеете сейчас, но в качестве отказоустойчивого, я думаю, что если среднестатистический пользователь собирается отказаться от навигации, сначала он переместит мышь в адресную строку, кнопка возврата или кнопку закрытия. Если вы захватите верхнюю часть окна DOM, возможно, получите еще несколько удачных сохранений в последнюю минуту?

Кроме того, вы можете добавить изменения на setTimeout(), но звучит так, будто вы стремитесь к чему-то более конечному, чем оба моих решения.

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