如何像 jQuery 一样使用 fetch() 来 POST 数据?

Roy*_*ubb 0 javascript php jquery fetch-api

我正在尝试从某些代码中删除 jQuery。我只将它用于 POST 操作,因此我想删除它并使用 fetch() 代替。但我无法使用相同的数据让 fetch() 工作。php文件工作正常,只是没有接收到数据

这将为以下两个测试用例设置测试数据:

var toPostObj = new(Object);
toPostObj.action = "update+file";
toPostObj.arrays = [["2020-12-28", "23:20:56", "Trying from ztest", "9.jpg"]];
Run Code Online (Sandbox Code Playgroud)

这可以使用 jQuery 来实现:

$.post('toMariaDB.php', {  // url
    data: toPostObj 
}, function(data2, status, jqXHR) {
    console.log ("data2",data2);
});
Run Code Online (Sandbox Code Playgroud)

使用 fetch() 不起作用:

fetch("toMariaDB.php", { 
    method: "POST", 
    body: toPostObj,   // using JSON.stringify(toPostObj) also doesn't work 
    headers: { "Content-type": "application/text; charset=UTF-8" } 
}) 
.then(response => response.text()) 
.then(text => console.log(text))//; 
.catch(error => {
    console.error(error)
})
Run Code Online (Sandbox Code Playgroud)

出于调试目的,toMariaDB.php 会写出它接收到的数据以及来自 toMariaDB 的任何其他消息的日志文件。
运行 jQuery 代码会将其写入日志文件:

toMariaDB: I've ARRIVED
in toMariaDB 1=>Array
(
    [action] => update+file
    [arrays] => Array
        (
            [0] => Array
                (
                    [0] => 2020-12-28
                    [1] => 23:20:56
                    [2] => Trying from ztest
                    [3] => 9.jpg
                )

        )
)
Run Code Online (Sandbox Code Playgroud)

这正是 toMariaDB.php 所期望的。
但 fetch() 版本是这样写的:

toMariaDB: I've ARRIVED
in toMariaDB 1=>
Run Code Online (Sandbox Code Playgroud)

无论我使用 fetch() 的结果是相同的

body: toPostObj,   
Run Code Online (Sandbox Code Playgroud)

或者

body: JSON.stringify(toPostObj),
Run Code Online (Sandbox Code Playgroud)

我用过

headers: { "Content-type": "application/text; charset=UTF-8" } 
Run Code Online (Sandbox Code Playgroud)

由于 toMariaDB.php 返回文本,据我了解,标头描述了返回的内容
,但以防万一我误解了,我尝试了

headers: { "Content-type": "application/json; charset=UTF-8" } 
Run Code Online (Sandbox Code Playgroud)

也是如此,但这也不起作用。

如何格式化主体,使其以与 jQuery 相同的形式到达 toMariaDB.php?IE

toPostObj.action = "update+file";
toPostObj.arrays = [["2020-12-28", "23:20:56", "Trying from ztest", "9.jpg"]];
Run Code Online (Sandbox Code Playgroud)

谢谢你的帮助。

编辑

正如 @TJCrowder 所建议的,(感谢您指出这一点)这是使用 jQuery 运行时“网络”选项卡显示为“请求有效负载”的内容:

data[action]: update+file
data[arrays][0][]: 2020-12-28
data[arrays][0][]: 23:20:56
data[arrays][0][]: Trying from ztest
data[arrays][0][]: 9.jpg
Run Code Online (Sandbox Code Playgroud)

我不明白为什么这些不显示为 data[arrays][0][0] 等,但它有效。
(这是一个 2D 数组,因为 toMariaDB.php 必须能够处理多个数组。)

使用 fetch(),“网络”选项卡“请求有效负载”显示:

[object Object]
Run Code Online (Sandbox Code Playgroud)

T.J*_*der 5

文档中我们可以看到...

当 data 是对象时,jQuery 会根据对象的键/值对生成数据字符串,除非该processData选项设置为 false。例如,{ a: "bc", d: "e,f" }转换为字符串"a=bc&d=e%2Cf"。如果该值是一个数组,jQuery 将根据传统设置的值(如下所述)序列化具有相同键的多个值。例如,成为默认设置的{ a: [1,2] }字符串。"a%5B%5D=1&a%5B%5D=2"traditional: false

(它没有这么说,但它是递归地执行的。)

您的代码正在发送一个对象,该对象具有一个名为的顶级属性,data其值为 your toPostObj,而该属性又具有带有字符串和数组值的属性。它最终会发送一个如下所示的 POST 正文:

data%5Baction%5D=update%2Bfile&data%5Barrays%5D%5B0%5D%5B%5D=2020-12-28&data%5Barrays%5D%5B0%5D%5B%5D=23%3A20%3A56&data%5Barrays%5D%5B0%5D%5B%5D=Trying+from+ztest&data%5Barrays%5D%5B0%5D%5B%5D=9.jpg
Run Code Online (Sandbox Code Playgroud)

...这些参数是:

data[action]: update+file
data[arrays][0][]: 2020-12-28
data[arrays][0][]: 23:20:56
data[arrays][0][]: Trying from ztest
data[arrays][0][]: 9.jpg
Run Code Online (Sandbox Code Playgroud)

您可以使用如下URLSearchParams对象复制它:

var toPostObj = new URLSearchParams();
toPostObj.append("data[action]", "update+file");
toPostObj.append("data[arrays][0][]", "2020-12-28");
toPostObj.append("data[arrays][0][]", "23:20:56");
toPostObj.append("data[arrays][0][]", "Trying from ztest");
toPostObj.append("data[arrays][0][]", "9.jpg");
fetch("foo", {
    method: "POST",
    body: toPostObj
})
// ...
Run Code Online (Sandbox Code Playgroud)

URLSearchParams将为您处理 URI 转义等。