Лучший способ определить, когда пользователь покидает веб-страницу?

Как лучше всего определить, покидает ли пользователь веб-страницу?

Событие onunload JavaScript не срабатывает каждый раз (HTTP-запрос занимает больше времени, чем требуется для завершения работы браузера).

Его создание, вероятно, будет заблокировано текущими браузерами.

Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
204
0
203 286
9
Перейти к ответу Данный вопрос помечен как решенный

Ответы 9

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

Конечно, это не сработает, если пользователь просто закроет окно браузера или введет новый URL.

Чтобы обойти это, вам, возможно, потребуется использовать на странице Javascript setTimeout (), выполняя вызов AJAX каждые несколько секунд (в зависимости от того, как быстро вы хотите узнать, ушел ли пользователь).

Если вы используете подход «Домой отчета», нет необходимости изменять каждую ссылку на странице.

Vinko Vrsalovic 29.09.2008 09:41
Ответ принят как подходящий

Попробуйте событие onbeforeunload: оно запускается непосредственно перед выгрузкой страницы. Это также позволяет вам спросить, действительно ли пользователь хочет уйти. Смотрите демонстрацию onbeforeunload Demo.

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

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

adam0101 11.09.2010 01:13

Также обратите внимание, что различные мобильные браузеры игнорируют результат события (то есть не запрашивают подтверждения у пользователя). Firefox имеет скрытое предпочтение в about: config, чтобы сделать то же самое. По сути, это означает, что пользователь всегда подтверждает, что документ может быть выгружен.

MJB 19.01.2015 20:29

Обратите внимание, что этот метод также активируется, когда пользователь обновляет страницу или отправляет форму.

Zaytsev Dmitry 20.01.2018 22:04

@Andreas Petersson, у меня та же проблема с целью прервать сеанс пользователя. Как я могу записать набранный URL-адрес, чтобы проверить, принадлежит ли он проекту?

Jcc.Sanabria 20.06.2018 01:31

В сети разработчиков Mozilla есть хорошее описание и пример перед выгрузкой.

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

window.addEventListener('beforeunload', function(e) {
  var myPageIsDirty = ...; //you implement this logic...
  if (myPageIsDirty) {
    //following two lines will cause the browser to ask the user if they
    //want to leave. The text of this dialog is controlled by the browser.
    e.preventDefault(); //per the standard
    e.returnValue = ''; //required for Chrome
  }
  //else: user is allowed to leave without a warning dialog
});

Я знаю, что на этот вопрос был дан ответ, но в случае, если вы хотите, чтобы что-то запускалось только при закрытии фактического BROWSER, а не только при загрузке страницы, вы можете использовать этот код:

window.onbeforeunload = function (e) {
        if ((window.event.clientY < 0)) {
            //window.localStorage.clear();
            //alert("Y coords: " + window.event.clientY)
        }
};

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

window.event для меня не определено

Karl Glaser 15.08.2014 08:30

Пример Merr Leader неверен, window.event следует использовать только как запасной вариант, например, для более старых версий IE, в других случаях следует использовать параметр события (в данном случае переменная e): stackoverflow.com/questions/9813445/…

Sk8erPeter 13.01.2015 16:47

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

Merr Leader 13.01.2015 23:57

Из MDN: This feature is non-standard and is not on a standards track. Do not use it on production sites facing the Web: it will not work for every user.developer.mozilla.org/en-US/docs/Web/API/Window/event

Robin Neal 20.01.2017 16:37

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

$(document).bind("mouseleave", function(e) {
    if (e.pageY - $(window).scrollTop() <= 1) {    
        $('#BeforeYouLeaveDiv').show();
    }
});

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

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

Leonardo Souza Paiva 09.08.2019 22:05

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

PHP:

session_start();

$_SESSION['ipaddress'] = $_SERVER['REMOTE_ADDR'];

if (isset($_SESSION['userID'])){
    if (!strpos($_SESSION['activeID'], '-')){
        $_SESSION['activeID'] = $_SESSION['userID'].'-'.$_SESSION['activeID'];
    }
}elseif (!isset($_SESSION['activeID'])){
    $_SESSION['activeID'] = time();
}

JS

window.setInterval(function(){
            var userid = '<?php echo $_SESSION['activeID']; ?>';
            var ipaddress = '<?php echo $_SESSION['ipaddress']; ?>';
            var action = 'data';

            $.ajax({
                url:'activeUser.php',
                method:'POST',
                data:{action:action,userid:userid,ipaddress:ipaddress},
                success:function(response){
                     //alert(response);                 
                }
            });
          }, 5000);

Ajax-вызов activeUser.php

if (isset($_POST['action'])){
    if (isset($_POST['userid'])){
        $stamp = time();
        $activeid = $_POST['userid'];
        $ip = $_POST['ipaddress'];

        $query = "SELECT stamp FROM activeusers WHERE activeid = '".$activeid."' LIMIT 1";
        $results = RUNSIMPLEDB($query);

        if ($results->num_rows > 0){
            $query = "UPDATE activeusers SET stamp = '$stamp' WHERE activeid = '".$activeid."' AND ip = '$ip' LIMIT 1";
            RUNSIMPLEDB($query);
        }else{
            $query = "INSERT INTO activeusers (activeid,stamp,ip)
                    VALUES ('".$activeid."','$stamp','$ip')";
            RUNSIMPLEDB($query);
        }
    }
}

База данных:

CREATE TABLE `activeusers` (
  `id` int(11) NOT NULL,
  `activeid` varchar(20) NOT NULL,
  `stamp` int(11) NOT NULL,
  `ip` text
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

Обычно каждые 5 секунд js отправляет сообщение в файл php, который будет отслеживать пользователя и его IP-адрес. Активные пользователи - это просто запись в базе данных, отметка времени в которой обновляется в течение 5 секунд. Старые пользователи перестают обновлять базу данных. IP-адрес используется только для того, чтобы гарантировать уникальность пользователя, чтобы 2 человека на сайте одновременно не регистрировались как 1 пользователь.

Возможно, не самое эффективное решение, но оно выполняет свою работу.

Благодаря Сервисные работники можно реализовать решение, подобное Адама, исключительно на стороне клиента, если браузер поддерживает его. Просто обходите запросы сердцебиения:

// The delay should be longer than the heartbeat by a significant enough amount that there won't be false positives
const liveTimeoutDelay = 10000
let liveTimeout = null

global.self.addEventListener('fetch', event => {
  clearTimeout(liveTimeout)
  liveTimeout = setTimeout(() => {
    console.info('User left page')
    // handle page leave
  }, liveTimeoutDelay)
  // Forward any events except for hearbeat events
  if (event.request.url.endsWith('/heartbeat')) {
    event.respondWith(
      new global.Response('Still here')
    )
  }
})

Вы имели в виду, что где-то в клиентском коде должен быть setInterval(() => fetch('/heartbeat'), 5000)?

Dan Dascalescu 29.05.2020 00:52

@DanDascalescu Верно. Код JS отправляет сетевой запрос в / heartbeat, и сервис-воркер его перехватывает.

Jeffrey Sweeney 30.05.2020 17:01

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

document.addEventListener('mouseleave', e=>{
     //do some async code
})

document.addEventListener('visibilitychange', e=>{
     if (document.visibilityState === 'visible') {
   //report that user is in focus
    } else {
     //report that user is out of focus
    }  
})

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

Другие вопросы по теме