AJAX: Как отправить простой параметр по POST в ванили JS - PullRequest
0 голосов
/ 17 апреля 2020

В jQuery код выглядит следующим образом, и все счастливы, как жаворонок:

$.post("bucket.php", { empty:"1" }, function(r) { ... });

Консоль в инструментах разработчика Firefox говорит, что «Данные формы» содержат empty=1 и файл PHP получает то, что хочет. Я не совсем понимаю этот синтаксис (что { } делает, а empty нет в кавычках), но он работает.

Теперь мне нужно сделать то же самое в простом Javascript. Вот мой код:

function bucketEmpty() {
  var xhr = new XMLHttpRequest();
  xhr.onreadystatechange = function() {
    if(xhr.readyState == 4 && xhr.status == 200) {  //no error
      if (!isNaN(xhr.responseText)) {  // return string is a number (expecting 0)
        document.getElementsByClassName('bucketcount').innerHTML = xhr.responseText;
      } else {
        alert(xhr.responseText);
      }
    }
  };
  xhr.open('POST', 'bucket.php');
  xhr.send(???what goes here???);
}

Для параметра xhr.send () я пробовал следующее, ни один из которых не работает:

  • 'empty=1' (согласно этот ответ ): консоль говорит, что она находится в «полезной нагрузке запроса», а не «данных формы».
  • {empty:"1"} или {"empty":"1"}: консоль говорит «полезная нагрузка запроса» содержит «[объект Object] ".
  • '{"empty":"1"}': консоль говорит, что находится в разделе с именем" JSON ".

Это будет легко с GET, но так как он что-то меняет на сервере, POST является более правильным. Какой правильный синтаксис?


РЕДАКТИРОВАТЬ в ответ Район и Атул Шарма:

Хм, что-то еще фундаментальное должно быть неправильно. Для диагностики у меня в настоящее время это первая строка в корзине. php:

die("GET:\n".print_r($_POST,true)."\nPOST:\n".print_r($_POST,true));

Использую ли я xhr.send(JSON.stringify({empty: '1'})) (ответ Атула Шармы) или xhr.send('{"empty":"1"}') (комментарий Района), я получаю результат, показанный на этом снимке экрана консоли и вывод с сервера: enter image description here

И я решил проверить GET - я изменил команду открытия на эту:

xhr.open('GET', 'bucket.php?empty=1');

Консоль сообщает, что Query String содержит empty: "1", но на сервере $_GET и $_POST все еще пусто! Ваниль JS просто ненавидит меня? Это прекрасно работает в jQuery.


РЕДАКТИРОВАТЬ # 2: Это только я (или мой сервер)!

После обнаружения, что даже мой оригинальный простейший синтаксис работает на jsfiddle (https://jsfiddle.net/3j42ztpf/), я написал пару тестовых файлов WME для своего собственного сервера. Как на моей локальной виртуальной машине, так и на моей производственной VPS она действует одинаково - jQuery работает, но обычная JS не работает, независимо от того, передается ли параметр в виде текста или JSON. Должно быть что-то другое в HTTP-запросе между тестом JSFiddle и первой ссылкой в ​​моем тесте сервера, но я не могу обнаружить это в devtools - полезная нагрузка запроса идентична, и различия в заголовках кажутся логичными. Попробуйте сами по адресу: https://dev.kizunadb.com/testajax.html

Тест внутреннего файла ajax. php содержит только это:

<?php
if (empty($_POST['text'])) {
  die('What do you want me to say?');
} else {
  die ($_POST['text']);
}

Так что я действительно это делаю есть более фундаментальная проблема, чем просто плохой синтаксис. Может кто-нибудь заметить проблему в своих инструментах разработки или предложить что-то, что я должен проверить на своем сервере?

1 Ответ

0 голосов
/ 20 апреля 2020

Исследуя предложения в комментариях @StackSlave и @Rayon, я узнал больше о Content-Type. Оказывается, все, что мне нужно было установить Content-Type на «application / x- www-form-urlencoded». Все три человека, которые пытались помочь (один из них удалил свой ответ позже), сосредоточились на передаче данных туда и обратно как JSON, но это действительно не нужно в этом случае и просто делает код труднее для чтения (на мой взгляд, в любом случае). Итак, вот окончательная версия функции, суть которой заключается в том, что последние две строки (мне также пришлось изменить способ записи возвращаемого числа в DOM - getElementsByClassName возвращает HTMLCollection, которая должна обрабатываться правильно):

function bucketEmpty() {
  var xhr = new XMLHttpRequest();
  xhr.onreadystatechange = function() {
    if(xhr.readyState === 4 && xhr.status === 200) {  //no error
      if (!isNaN(xhr.responseText)) {  // return string is a number (expecting 0)
        var elements = document.getElementsByClassName('bucketcount');
        [].forEach.call(elements, function (el) { el.innerHTML = xhr.responseText; });
      } else {
        alert(xhr.responseText);
      }
    }
  };
  xhr.open('POST', 'bucket.php');
  xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
  xhr.send('empty=1');
}

Особенно полезными SO-ответами и другими страницами были:

...