Закрытие окна Chrome не отправляет данные с помощью sendBeacon в обработчике событий выгрузки

Я пытаюсь отправить данные, когда окно закрывается, чтобы два человека не могли редактировать и перезаписывать данные друг друга. В настоящее время я использую sendBeacon в обработчике событий выгрузки.

Fire Fox:

  • Обновить: работает
  • Кнопка «Назад»: работает
  • Закрыть окно: работает

Хром:

  • Обновить: работает
  • Кнопка «Назад»: работает
  • Закрыть окно: не работает

Вот мой код

function sendDataOnClose(edit,trans){

    var url = "../../save.php"; //This has a post request handler and works properly with other functions for saving data

    const data = JSON.stringify
    ({
      "translations": trans,
      "edit": edit
    });

    navigator.sendBeacon(url, data);
  }

function handleClose(){
    if(edit){
      console.log("sending a false when edit is: "+ edit)
      sendDataOnClose(false, translations);
    }
  }

window.addEventListener('unload', handleClose); 

person webdevtrev    schedule 10.11.2020    source источник
comment
Несмотря на то, что в документации указано unload and beforeunload aren’t the right events to use with sendBeacon. Instead, use visibilitychange., оно также не работает при закрытии с событием visibilitychange!   -  person Brackets    schedule 23.12.2020


Ответы (2)


В последней документации sendBeacon на MDN говорится, что Navigator Метод .sendBeacon() асинхронно отправляет небольшой объем данных по HTTP на веб-сервер. Он предназначен для использования в сочетании с событием visibilitychange (но не с событиями unload и beforeunload).

Чтобы использовать событие visibilitychange, как было предложено, вы можете

document.addEventListener('visibilitychange', function() {
  if (document.visibilityState === 'hidden') {
    navigator.sendBeacon(handleClose);
  }
});

У меня возникли аналогичные проблемы с попыткой отправить данные о событии unload. Все ли пользователи на рабочем столе? Мобильные устройства не всегда надежно запускают событие unload. API жизненного цикла страницы обеспечивает событие изменения видимости и pagehide событий, которые можно использовать вместе, чтобы приблизиться к желаемому результату.

Page Lifecycle API пытается решить эту проблему следующим образом: Введение и стандартизация концепции состояний жизненного цикла в Интернете. Определение новых, инициируемых системой состояний, которые позволяют браузерам ограничивать ресурсы, которые могут потребляться скрытыми или неактивными вкладками. Создание новых API и событий, которые позволяют веб-разработчикам реагировать на переходы в эти новые состояния, инициируемые системой, и из них. источник

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

Есть несколько тем, которые углубляются в эту проблему, если вам это интересно. Пока браузеры не стандартизируют это, я не уверен, что есть простой ответ, такой как use x event.

Ошибка в отношении видимости страницы

Проблема с рекомендациями MDN по поводу sendBeacon

person mitchellcarroll    schedule 23.12.2020
comment
pagehide или visbilitychange не срабатывают при закрытии вкладки. Это проблема. Мне нужно любое событие, которое срабатывает при закрытии окна, и ни одно из них не сработало. - person Brackets; 23.12.2020
comment
Пожалуйста, произносите это как видимость, а не видимость. - person Janos Vinceller; 30.12.2020

Благодаря хакерам многие другие вещи удалены из соображений безопасности.

Я заметил, что в вашем вопросе также был тег PHP; Я дам вам не очень хорошую идею, но функциональную. Избегайте обработки на закрытой странице даже JavaScript или фреймворков, просто публикуйте с помощью JavaScript базу данных таблиц, в которой вы храните time(), и целевой идентификатор, а затем, если время ожидания может быть больше 30 секунд, которое вы установили, вы удалите из таблицы этот материал, и вы будете знать эта страница все еще не работает (перевод: используйте идею онлайн-пользователей сервера (плохая, но необходимая, как и все, что генерирует много трафика в приложении).

Использование их в JavaScript в стороннем клиенте — плохая идея, и вы открываете ворота для плохих парней, которые будут эксплуатировать ваше приложение.

person Constantin    schedule 26.12.2020
comment
У меня уже есть тайм-аут на стороне сервера. Я хочу закончить таймер, когда пользователь закрывает страницу. - person Brackets; 26.12.2020
comment
@Brackets, тогда все очень просто! время ожидания должно истечь само по себе.: каждый раз, когда цель пользователя или другой пользователь входят при запуске скрипта, вы должны проверять все тайм-ауты и удалять их, которые отсутствуют, вы - целевое время начала, поэтому вы можете обрабатывать закрытую страницу на сервере по тайм-ауту, проверив запускать и прекращать обращение к текущему php time(); в зависимости от разницы тайм-аутов - person Constantin; 26.12.2020
comment
Пожалуйста, отредактируйте ответ, чтобы включить эту идею. - person Janos Vinceller; 30.12.2020
comment
@Janos Vinceller Я мог бы написать сценарий php mysql, чтобы продемонстрировать ОНЛАЙН-ПОЛЬЗОВАТЕЛЯМ запуск, а затем остановку обработчика проверки php, но это не будет тем, что я думаю на 100% (в моем случае код этих ситуаций присутствует до того, как он мне понадобится, в моих фреймворках, поэтому я не буду проверять на stackoverflow ответ, который я пока знаю). О части предотвращения взлома я больше не буду публиковать что-то, что может дать идею ребятам, которых я пытаюсь остановить в своих приложениях.. Так что, если вам не нравится ответ, я мог бы убери это - person Constantin; 31.12.2020