Как отправить запрос AJAX, когда пользователь уходит (закрывает) страницу?

Ситуация

Привет, Я делаю игру с управляемой базой данных, в которой возникает вопрос, и пользователь получает право изменить вопрос (то есть написать новый вопрос), если найдет правильный ответ.

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

  • Пользователь 1 находит ответ
  • Пользователю 1 предлагается ввести новый вопрос
  • Прежде чем пользователь 1 представит новый вопрос, Пользователь 2 также найдет новый ответ
  • Теперь это только удача, кто задает новый вопрос. Если Пользователь 2 отправляет вопрос после пользователя 1, вопрос пользователя 2 перезаписывает вопрос пользователя 1.

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

  • Пользователь 1 находит ответ
  • Семафор сохраняется в базе данных, например ['user_ip' = 'xx' , 'time'='yy' , 'locked'='true']
  • Семафор истекает через t секунд
  • Новый вопрос будет принят только в том случае, если семафор истек.

поэтому при отправке нового вопроса приложение принимает его только в том случае, если семафор не заблокирован, а текущее время больше на t (15) секунд, чем дата семафора.

Но это тоже проблема, запрос User 2

«Вы нашли ответ, но кто-то нашел его перед вами. Вы можете изменить вопрос, если он не представит новый вопрос за 15 секунд».

Таким образом, новый победитель должен ждать 15 секунд, возможно, без необходимости.

Следовательно,

Что я хочу сделать

Я хочу пригласить «победителя» форму с секундомером (счетчиком времени). Когда он достигает нуля, он разблокирует семафор, чтобы новый победитель мог представить свой вопрос.

Но это решение будет иметь эту проблему:

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

Поэтому я должен убедиться, что я вызвал userLeave(); если пользователь закрывает страницу.

Google предлагает onbeforeunload и onunload но люди также жалуются на то, что эти функции не работают. Таким образом, существует 100% -ный способ отправить этот вызов AJAX, если пользователь (победитель) покидает страницу?

Есть ли 100% -ный способ отправить этот вызов AJAX, если пользователь (победитель) покидает страницу?

Вы никогда не сможете полагаться на то, что клиент делает что-то 100%. Подумайте о потерях в сети, сбоях браузера, недоступных функциях (из браузеров, несовместимых с HTML5, с отключенным javascript), ошибок сценариев, неправильно настроенных агентов, которые вызывают (или нет) ваш API неожиданными способами или хакерами, делающими то же самое специально …

Единственное, что вы можете ожидать от клиента, это то, что он ничего не делает – это называется тайм-аутом.

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

Кстати: Пока я не знаю вашу игру, было бы проще и, вероятно, более комфортно, если бы вы просто приняли оба новых вопроса 🙂