简体   繁体   English

如何通过 JS fetch 向服务器发送数据/从服务器接收数据

[英]How to send/receive data to/from server via JS fetch

I'm new to fetch and I'm trying to convert $ajax into fetch without await, async.. (I didn't make it till there).我是 fetch 的新手,我正在尝试将 $ajax 转换为 fetch而无需等待,async .. (直到那里我才成功)。 I'm using Express for the server.我正在为服务器使用 Express。

The fundamental concept of fetch/promise is unclear for me and I don't know how can I send the parameter selected in JSON format, and how to receive it from the server. fetch/promise 的基本概念对我来说还不清楚,我不知道如何发送以 881569990078588 格式selected的参数,以及如何从服务器接收它。 I thought I would be ok to receive it (from server-side) with JSON.parse(req.body.data) , and I tried several things with it but it keeps giving me errors both on client-side and server-side(errors are down below).我以为我可以用JSON.parse(req.body.data)接收它(从服务器端),我尝试了一些东西但它在客户端和服务器端都给我错误(错误在下面)。

** I tried Fetch: POST json data from someone's feedback but sadly I couldn't make it work for me. ** 我尝试从某人的反馈中获取:POST json 数据,但遗憾的是我无法让它为我工作。 ** **

Any help would be appreciated.任何帮助,将不胜感激。

addProduct(selected) { 
        const orderList = this;

        function post(){
        
            // const data = {
            //     selected:"selected",
            // }        

            fetch('/cart', {
                method:'post',
                headers:{
                    "Accept": "application/json, text/plain, */*",
                    "Content-type": "application/json; charset = UTF-8"
                },
                body: JSON.stringify(selected),
            })
            .then(res => {
                res.json()
                console.log(res)})
            .then(res => console.log(res));
        }
        
        post();
}

server-side error: SyntaxError: Unexpected token u in JSON at position 0服务器端错误: SyntaxError: Unexpected token u in JSON at position 0

client-side error: Uncaught (in promise) SyntaxError: Unexpected token < in JSON at position 0客户端错误: Uncaught (in promise) SyntaxError: Unexpected token < in JSON at position 0

(the following codes are the original $ajax code that works) (以下代码是有效的原始 $ajax 代码)

Client-side客户端

menuItemClick(target) {
        const selected = this.menuList.data.find(product => product.id == target.dataset.id)
        const selectedIndex = this.orderList.data.findIndex(product => product.id == selected.id)
        if (selectedIndex === -1) {
            selected.count = 1;
            this.orderList.addProduct(selected)
    }



addProduct(selected) { 
        const orderList = this;
        $.ajax({
            url:"http://localhost:8080/cart",
            type:"post",
            dataType: "json",
            data: {data:JSON.stringify(selected)},
            success: function(orderedItem){
                orderList.data.push(orderedItem),
                orderList.orderRender()
            }
        })
        
    }

Server-side服务器端

app.use(express.json());
app.use(express.urlencoded({ extended: false }));

app.post("/cart", (req, res) => {
    const bodyData = JSON.parse(req.body.data);
    db.query(
        `INSERT INTO cartData (prodId) VALUES(${bodyData.id})`,(err, rows) => {
            db.query(
                `SELECT cartData.id as orderId, prodName, price, category, count, menuData.Id as id FROM menuData JOIN cartData on menuData.id = cartData.prodId where prodId = ${bodyData.id}`,
                (err, orderedItem) => {
                    res.send({"orderedItem": "${orderedItem[0]}"});
                }
            );
        }
    );
});

You're really close, just a few things:你真的很接近,只有几件事:

  1. (Client side) You need to check for HTTP success. (客户端)您需要检查 HTTP 是否成功。 Unfortunately, fetch only rejects its promise when there's a network failure, not an HTTP error.不幸的是,当出现网络故障时, fetch只会拒绝其 promise,而不是 HTTP 错误。

  2. (Client side) You need to use the return value of res.json() , which is a promise, so you want to return it from the fulfillment handler. (客户端)您需要使用res.json()的返回值,它是一个 promise,因此您想从履行处理程序中返回它。

  3. (Client side) You need to either handle errors, or return the promise chain to something that will. (客户端)您需要处理错误,或者将 promise 链返回给可以处理的东西。

  4. (Server side) You're sending the text [object Object] , not JSON; (服务器端)您发送的是文本[object Object] ,而不是 JSON; more below.更多如下。

  5. (Server side) The error you're getting suggests there's some other problem with the server-side code; (服务器端)您收到的错误表明服务器端代码存在其他问题; more below.更多如下。

  6. (Server side) Your code is at risk of SQL injection attacks ; (服务器端)您的代码存在 SQL 注入攻击的风险 more below.更多如下。

So for example, if you want to handle errors in post and not have post report success/failure to its calller:因此,例如,如果您想处理postpost错误并且不向其调用者报告成功/失败:

fetch('/cart', {
    method:'post',
    headers:{
        "Accept": "application/json, text/plain, */*",
        "Content-type": "application/json; charset = UTF-8"
    },
    body: JSON.stringify(selected),
})
.then(res => {
    if (!res.ok) {                                   // ***
        throw new Error("HTTP error " + res.status); // *** #1
    }                                                // ***
    return res.json();                               // *** #2
})
.then(data => {
    // *** Use `data` here
})
.catch(error => {
    // *** Handle/report error here                  // *** #3
});

Regarding #4, you're doing this to send the information:关于#4,您这样做是为了发送信息:

res.send({"orderedItem": "${orderedItem[0]}"});

send expects a Buffer, a string, or an Array. send需要一个缓冲区、一个字符串或一个数组。 To convert something to JSON and send that instead, use json :要将某些内容转换为 JSON 并改为发送,请使用json

res.json({"orderedItem": "${orderedItem[0]}"});

Also note that that will send exactly this JSON:另请注意,这将准确发送此 JSON:

{"orderedItem":"${orderedItem[0]}"}

I suspect you wanted a template literal there so that the value of orderedItem[0] was sent, like this:我怀疑你想要一个模板文字,以便发送orderedItem[0]的值,如下所示:

res.json({"orderedItem": `${orderedItem[0]}`});
// −−−−−−−−−−−−−−−−−−−−−−^−−−−−−−−−−−−−−−−−^

But if it's just orderedItem[0] , you don't need a template literal, just:但如果只是orderedItem[0] ,则不需要模板文字,只需:

res.json({"orderedItem": orderedItem[0]});

or if you want to convert it to string:或者如果你想将它转换为字符串:

res.json({"orderedItem": String(orderedItem[0])});

(You also don't need the " on the orderedItem property name because you're using an object literal there, you're not writing the JSON; but they're harmless in this case, and would be needed if you had a property name with a - or something in it.) (您也不需要orderedItem属性名称上的" ,因为您在那里使用的是 object 文字,您没有写 JSON;但在这种情况下它们是无害的,如果您有属性,则需要它们名称中带有-或其他内容。)

Regarding #5, you've said the error is:关于#5,你说错误是:

Uncaught (in promise) SyntaxError: Unexpected token < in JSON at position 0未捕获(承诺)SyntaxError:意外令牌 < in JSON at position 0

That suggests that you're getting an error, not data, because the first token in what you were sending wouldn't have been a < but it would be if you were sending an HTML error page instead.这表明您收到的是错误,而不是数据,因为您发送的内容中的第一个标记不会是<但如果您发送的是 HTML 错误页面,它就会是。 Hopefully thanks to #2 above you'll now be taking the error path and will be able to find out what that error is.希望感谢上面的#2,您现在可以找到错误路径,并且能够找出错误是什么。 It's not immediately obvious from the code you've shown what that error is (unless bodyData.id is textual, not numeric), so you'll need to debug it.从代码中不能立即看出错误是什么(除非bodyData.id是文本的,而不是数字的),因此您需要对其进行调试。

Regarding #6, you have this template literal you're using to create your SQL:关于#6,你有这个模板文字用于创建你的 SQL:

`INSERT INTO cartData (prodId) VALUES(${bodyData.id})`

NEVER use information you've received from the client without sanitizing it.切勿使用您从客户那里收到的未经净化的信息。 In that template literal, you've just accepted what was provided.在该模板文字中,您刚刚接受了所提供的内容。 The problem is that it could be something malicious, or just something whimsical.问题是它可能是恶意的,或者只是异想天开的东西。 (Let me introduce you to my friend Bobby .) (让我把你介绍给我的朋友鲍比。)

Instead, use the feature of whatever it is providing db to create a parameterized query .相反,使用它提供db的任何功能来创建参数化查询 Never use text concatenation with client-supplied values to build SQL strings.切勿将文本连接与客户端提供的值一起构建 SQL 字符串。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM