使用 XMLHttpRequest 发送 POST 数据

IT技术 javascript ajax forms post xmlhttprequest
2021-01-08 16:44:34

我想在 JavaScript 中使用 XMLHttpRequest 发送一些数据。

假设我在 HTML 中有以下表单:

<form name="inputform" action="somewhere" method="post">
  <input type="hidden" value="person" name="user">
  <input type="hidden" value="password" name="pwd">
  <input type="hidden" value="place" name="organization">
  <input type="hidden" value="key" name="requiredkey">
</form>

如何在 JavaScript 中使用 XMLHttpRequest 编写等效项?

6个回答

下面的代码演示了如何做到这一点。

var http = new XMLHttpRequest();
var url = 'get_data.php';
var params = 'orem=ipsum&name=binny';
http.open('POST', url, true);

//Send the proper header information along with the request
http.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');

http.onreadystatechange = function() {//Call a function when the state changes.
    if(http.readyState == 4 && http.status == 200) {
        alert(http.responseText);
    }
}
http.send(params);

如果您拥有/创建一个对象,您可以使用以下代码将其转换为参数,即:

var params = new Object();
params.myparam1 = myval1;
params.myparam2 = myval2;

// Turn the data object into an array of URL-encoded key/value pairs.
let urlEncodedData = "", urlEncodedDataPairs = [], name;
for( name in params ) {
 urlEncodedDataPairs.push(encodeURIComponent(name)+'='+encodeURIComponent(params[name]));
}
是否可以params像在 jQuery 中那样发送对象而不是字符串?
2021-02-08 16:44:34
@EdHeal,ConnectionContent-Length头不能设置。它会说 "Refused to set unsafe header "content-length"" 。参见stackoverflow.com/a/2624167/632951
2021-02-10 16:44:34
可以发送application/json请求吗?
2021-02-19 16:44:34
不,但@Vadorequest 的评论提到了 jQuery - 他问是否可以“像 jQuery”一样传递数据。我提到了我认为 jQuery 如何做到这一点,以及如何实现这一点。
2021-02-28 16:44:34
注意:setRequestHeader()open() 之后。花了我一个小时,希望这条评论能帮我节省一个小时;)
2021-03-02 16:44:34
var xhr = new XMLHttpRequest();
xhr.open('POST', 'somewhere', true);
xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
xhr.onload = function () {
    // do something to response
    console.log(this.responseText);
};
xhr.send('user=person&pwd=password&organization=place&requiredkey=key');

或者,如果您可以依靠浏览器支持,您可以使用FormData

var data = new FormData();
data.append('user', 'person');
data.append('pwd', 'password');
data.append('organization', 'place');
data.append('requiredkey', 'key');

var xhr = new XMLHttpRequest();
xhr.open('POST', 'somewhere', true);
xhr.onload = function () {
    // do something to response
    console.log(this.responseText);
};
xhr.send(data);
是的,但问题是编写与提供的表单等效的 JavaScript,而不是使用 JavaScript 提交表单。
2021-02-08 16:44:34
@uKolka 应该在回复中注明,而不是使用您的第二个解决方案,请求Content-Type会自动更改为multipart/form-data这对服务器端以及在那里访问信息的方式有严重的影响。
2021-02-16 16:44:34
票数很少但被标记为正确的答案使用了两个额外的标题:http.setRequestHeader("Content-length", params.length);http.setRequestHeader("Connection", "close");. 他们需要吗?它们可能只在某些浏览器上需要吗?(在另一个页面上有一条评论说设置 Content-Length 标头是“正是需要的”)
2021-02-17 16:44:34
@Darren Cook 依赖于实现。根据我的经验,主要浏览器会根据您提供的数据自动设置“内容长度”(这是必需的)在大多数情况下,'Connection'标头默认为 'keep-alive',这会保持连接打开一段时间,因此后续请求不必像在 'close' 的情况下再次重新建立连接。您可以在控制台中尝试这些片段,使用当前页面 URL 并使用浏览器的工具或wireshark检查请求标头
2021-02-25 16:44:34
FormData 以表单元素作为其构造函数参数,无需单独添加值
2021-03-05 16:44:34

使用现代 JavaScript!

我建议调查一下fetch它与 ES5 等效并使用 Promises。它更具可读性且易于定制。

const url = "http://example.com";
fetch(url, {
    method : "POST",
    body: new FormData(document.getElementById("inputform")),
    // -- or --
    // body : JSON.stringify({
        // user : document.getElementById('user').value,
        // ...
    // })
}).then(
    response => response.text() // .json(), etc.
    // same as function(response) {return response.text();}
).then(
    html => console.log(html)
);

在 Node.js 中,您需要fetch使用以下命令导入

const fetch = require("node-fetch");

如果你想同步使用它(在顶级范围内不起作用):

const json = await fetch(url, optionalOptions)
  .then(response => response.json()) // .text(), etc.
  .catch((e) => {});

更多信息:

Mozilla 文档

我可以使用吗(2020 年 11 月 96%)

大卫沃尔什教程

对于对网页功能至关重要的事情,您应该避免使用 Promise 和粗箭头,因为许多设备没有支持这些功能的浏览器。
2021-02-16 16:44:34
Promise已覆盖 90%。我添加了function()示例,以防您不喜欢=>. 您绝对应该使用现代 JS 来简化开发人员的体验。担心一小部分人坚持使用 IE 是不值得的,除非你是一家大企业
2021-02-20 16:44:34
胖箭头也不适用于this关键字。我喜欢提到这一点,但我也暗中讨厌使用this, 和继承架构而不是函数工厂的人。原谅我,我是节点。
2021-02-22 16:44:34
如果担心兼容性...Google es6 转译器... stackoverflow.com/questions/40205547 /... 写得简单点。部署它兼容。+1 避免this
2021-02-22 16:44:34
我也this像瘟疫一样避免,任何阅读的人也应该如此this
2021-03-05 16:44:34

这是一个完整的解决方案application-json

// Input values will be grabbed by ID
<input id="loginEmail" type="text" name="email" placeholder="Email">
<input id="loginPassword" type="password" name="password" placeholder="Password">

// return stops normal action and runs login()
<button onclick="return login()">Submit</button>

<script>
    function login() {
        // Form fields, see IDs above
        const params = {
            email: document.querySelector('#loginEmail').value,
            password: document.querySelector('#loginPassword').value
        }

        const http = new XMLHttpRequest()
        http.open('POST', '/login')
        http.setRequestHeader('Content-type', 'application/json')
        http.send(JSON.stringify(params)) // Make sure to stringify
        http.onload = function() {
            // Do whatever with response
            alert(http.responseText)
        }
    }
</script>

确保您的后端 API 可以解析 JSON。

例如,在 Express JS 中:

import bodyParser from 'body-parser'
app.use(bodyParser.json())
鉴于默认值为 true,我将从示例中删除它并删除此 URL 以进行研究:developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/open
2021-02-08 16:44:34
很好,但不要对 XMLHttpRequest.open 中的 async 参数使用“false”值 - 它已被弃用并会发出警告
2021-02-18 16:44:34
我更喜欢这样,因为它是合理的,并且对于某人开始时少了一个细节。感谢您强调它。
2021-02-20 16:44:34
它应该默认为 true 但我不知道是否所有浏览器都尊重它
2021-03-03 16:44:34
我们应该把 true 放在那里还是只是省略那个参数?如果您可以指定哪个更可取,我会更新答案。
2021-03-05 16:44:34

最少使用FormData提交 AJAX 请求

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=Edge, chrome=1"/>
<script>
"use strict";
function submitForm(oFormElement)
{
  var xhr = new XMLHttpRequest();
  xhr.onload = function(){ alert (xhr.responseText); } // success case
  xhr.onerror = function(){ alert (xhr.responseText); } // failure case
  xhr.open (oFormElement.method, oFormElement.action, true);
  xhr.send (new FormData (oFormElement));
  return false;
}
</script>
</head>

<body>
<form method="post" action="somewhere" onsubmit="return submitForm(this);">
  <input type="hidden" value="person"   name="user" />
  <input type="hidden" value="password" name="pwd" />
  <input type="hidden" value="place"    name="organization" />
  <input type="hidden" value="key"      name="requiredkey" />
  <input type="submit" value="post request"/>
</form>
</body>
</html>

评论

  1. 这并不能完全回答 OP 问题,因为它需要用户单击才能提交​​请求。但这可能对寻找这种简单解决方案的人有用。

  2. 这个例子很简单,不支持该GET方法。如果您对更复杂的示例感兴趣,请查看优秀的MDN 文档另请参阅有关XMLHttpRequest to Post HTML Form 的类似答案

  3. 此解决方案的局限性:正如Justin BlankThomas Munk所指出的(见他们的评论),FormDataIE9 及更低版本不支持,Android 2.3 上的默认浏览器不支持。

感谢@ThomasMunk 提供您的链接 :-) 我们看到FormData除 IE9 和 Android 2.3(以及 OperaMini 但最后一个没有被广泛使用)之外的许多浏览器都支持它。干杯;-)
2021-03-01 16:44:34
唯一的一点是我认为 FormData 在 IE 9 中不可用,所以它不会被很多没有 polyfill 的人使用。developer.mozilla.org/en-US/docs/Web/API/FormData
2021-03-07 16:44:34