JavaScript AJAX запрос создает дублированные записи в базе данных

Проблема с дублированием AJAX запросов

Столкнулся с проблемой при работе с асинхронными JavaScript запросами. При отправке AJAX запроса на PHP скрипт, который добавляет данные в базу, почему-то создается две одинаковые записи вместо одной.

document.addEventListener('DOMContentLoaded', function(){
    var request;
    if (window.XMLHttpRequest) {
        request = new XMLHttpRequest();
    } else {
        request = new ActiveXObject('Microsoft.XMLHTTP');
    }
    
    request.onreadystatechange = function() {
        if (request.readyState === 4 && request.status === 200) {
            console.log(request.responseText);
            return;
        }
    }
    
    var params = 'user_id=' + userData['id'] + '&page_url=' + encodeURIComponent(currentURL) + '&token=' + userData['token'];
    request.open('POST', 'https://mysite.com/handlers/save_visit.php?' + params, true);
    request.send();
});

PHP скрипт выполняет INSERT в таблицу и возвращает ID новой записи. В консоли вижу правильный ID, но в базе данных оказывается две записи с разницей в несколько миллисекунд. Подозреваю что запрос отправляется несколько раз пока не получит readyState 4. Как это исправить?

У меня была такая же фигня! Проблема скорее всего не в readyState - DOMContentLoaded может срабатывать дважды или скрипт подключается несколько раз. Добавь флаг или отключай кнопку после первого клика. И глянь в Network tab - сколько запросов реально уходит?

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

Проверь, загружается ли твой скрипт дважды на странице. Или, возможно, ты прикрепляешь обработчик событий несколько раз. Попробуй добавить флаг, например, var requestSent = false; перед запросом и проверь его. Если запрос уже отправлен, то просто вернись. Также перенеси параметры в тело POST запроса, а не в URL.