【问题标题】:AJAX: How to send a simple parameter by POST in vanilla JSAJAX:如何在 vanilla JS 中通过 POST 发送简单参数
【发布时间】:2020-04-17 04:30:25
【问题描述】:

在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'(根据this answer):控制台说它在“请求有效负载”中,而不是“表单数据”中。
  • {empty:"1"}{"empty":"1"} :控制台显示“请求有效负载”包含“[object Object]”。
  • '{"empty":"1"}' :控制台说它在一个名为“JSON”的部分中。

使用 GET 很容易,但由于它正在更改服务器上的某些内容,因此 POST 更合适。什么是正确的语法?


编辑以回应 Rayon 和 Atul Sharma:

嗯,其他基本的东西一定是错的。对于诊断,我目前将此作为 bucket.php 中的第一行:

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

无论我使用xhr.send(JSON.stringify({empty: '1'}))(Atul Sharma 的回答)还是xhr.send('{"empty":"1"}')(Rayon 的评论),我都得到了控制台屏幕截图和服务器输出中显示的结果:

我决定测试 GET - 我将打开命令更改为:

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

控制台说查询字符串包含empty: "1",但在服务器上$_GET$_POST仍然为空! vanilla JS只是恨我吗?这在 jQuery 中运行良好。


编辑 #2:只有我(或我的服务器)!

在发现即使我最初最简单的语法也适用于 jsfiddle (https://jsfiddle.net/3j42ztpf/) 后,我为自己的服务器编写了一个 WME 测试文件对。在我的本地 VM 和生产 VPS 上,它的行为方式相同 - jQuery 可以工作,但普通 JS 不能,无论参数是以文本还是 JSON 形式发送。 JSFiddle 测试和我的服务器测试上的第一个链接之间的 HTTP 请求肯定有一些不同,但我无法在 devtools 中发现它 - 请求有效负载是相同的,并且标头中的差异似乎都是合乎逻辑的。亲自尝试:https://dev.kizunadb.com/testajax.html

后端文件 testajax.php 只包含这个:

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

所以我确实有一个比语法错误更根本的问题。任何人都可以在他们的开发工具中发现问题,或者建议我应该在我的服务器上检查的内容吗?

【问题讨论】:

  • 我在'{"empty":"1"}' 中没有发现任何问题,但服务器应该能够理解内容类型。
  • @Rayon:我更新了我的问题 - 显然还有一些其他瓶颈,因为我尝试了 GET,但它也没有用!
  • 您应该将FormData 的实例传递给.send(formDataInstanceHere)。顺便说一句,你可以像 xhr.onload = function(){ const obj = JSON.parse(xhr.responseText); } 那样做。
  • @OsakaWebbie - 我不确定 php 7 是如何工作的,我已经很久没有使用它了。尝试了这个例子,因为你很难理解一件事,$data = json_decode(file_get_contents('php://input'), true); 是我们检索发布数据的一些新方法。它对我有用。告诉我。
  • @Rayon PHP7 在这方面与旧版本没有什么不同(除了 $HTTP_RAW_POST_DATA 被删除)。 php://input 一点也不新鲜,但在你提到它之前我从未听说过它!我不想将它用作我的最终解决方案,因为它需要解析才能获得 $_GET 和 $_POST 已经提供的内容,但它帮助我了解正在发生的事情,并且将其包含在 Google 搜索中会引导我找到包含线索的页面需要。谢谢。

标签: javascript ajax post xmlhttprequest


【解决方案1】:

在研究来自 @StackSlave 和 @Rayon 的 cmets 中的建议时,我了解了有关 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 答案和其他页面是:

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-25
    • 2018-03-08
    相关资源
    最近更新 更多