JavaScript thuần gửi dữ liệu POST mà không cần biểu mẫu


138

Có cách nào để gửi dữ liệu bằng phương thức POST mà không cần biểu mẫu và không làm mới trang chỉ bằng JavaScript thuần túy (không phải jQuery $.post()) không? Có thể httprequesthoặc một cái gì đó khác (không thể tìm thấy nó bây giờ)?


1
XMLHttpRequest là câu trả lời ... $. Bài viết sử dụng tương tự dưới mui xe.
Chandu

Câu trả lời:


138

Bạn có thể gửi nó và chèn dữ liệu vào phần thân:

var xhr = new XMLHttpRequest();
xhr.open("POST", yourUrl, true);
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.send(JSON.stringify({
    value: value
}));

Nhân tiện, để nhận yêu cầu:

var xhr = new XMLHttpRequest();
// we defined the xhr

xhr.onreadystatechange = function () {
    if (this.readyState != 4) return;

    if (this.status == 200) {
        var data = JSON.parse(this.responseText);

        // we get the returned data
    }

    // end of state change: it can be after some time (async)
};

xhr.open('GET', yourUrl, true);
xhr.send();

2
Biến boolean thực trong xhr.open để làm gì?
Hylle


67

[New-ish tại thời điểm viết vào năm 2017] API tìm nạp nhằm mục đích làm cho các yêu cầu GET trở nên dễ dàng, nhưng nó cũng có thể POST.

let data = {element: "barium"};

fetch("/post/data/here", {
  method: "POST", 
  body: JSON.stringify(data)
}).then(res => {
  console.log("Request complete! response:", res);
});

Nếu bạn lười như tôi (hoặc chỉ thích một phím tắt / người trợ giúp):

window.post = function(url, data) {
  return fetch(url, {method: "POST", body: JSON.stringify(data)});
}

// ...

post("post/data/here", {element: "osmium"});

54

Bạn có thể sử dụng XMLHttpRequestđối tượng như sau:

xhr.open("POST", url, true);
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
xhr.send(someStuff);

Mã đó sẽ được đăng someStufflên url. Chỉ cần đảm bảo rằng khi bạn tạo XMLHttpRequestđối tượng của mình , nó sẽ tương thích với nhiều trình duyệt. Có những ví dụ bất tận về cách làm điều đó.


1
bạn có thể viết một ví dụ cho someStuff?
Huỳnh

4
someStuff = 'param1 = val1 & param2 = val2 & param3 = val3'
Lạc đà

1
Đó là một câu trả lời tốt, và someStuffcó thể là bất cứ điều gì bạn muốn ngay cả một chuỗi đơn giản. bạn có thể kiểm tra yêu cầu bằng các dịch vụ trực tuyến như mục yêu thích cá nhân của tôi: ( requestb.in )
JamesC

các application/x-www-form-urlencodedloại MIME không có một charsettham số: iana.org/assignments/media-types/application/...
JBG

28

Ngoài ra, RESTful cho phép bạn lấy lại dữ liệu từ yêu cầu POST .

JS (đặt tĩnh / hello.html để phân phát qua Python):

<html><head><meta charset="utf-8"/></head><body>
Hello.

<script>

var xhr = new XMLHttpRequest();
xhr.open("POST", "/postman", true);
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.send(JSON.stringify({
    value: 'value'
}));
xhr.onload = function() {
  console.log("HELLO")
  console.log(this.responseText);
  var data = JSON.parse(this.responseText);
  console.log(data);
}

</script></body></html>

Máy chủ Python (để thử nghiệm):

import time, threading, socket, SocketServer, BaseHTTPServer
import os, traceback, sys, json


log_lock           = threading.Lock()
log_next_thread_id = 0

# Local log functiondef


def Log(module, msg):
    with log_lock:
        thread = threading.current_thread().__name__
        msg    = "%s %s: %s" % (module, thread, msg)
        sys.stderr.write(msg + '\n')

def Log_Traceback():
    t   = traceback.format_exc().strip('\n').split('\n')
    if ', in ' in t[-3]:
        t[-3] = t[-3].replace(', in','\n***\n***  In') + '(...):'
        t[-2] += '\n***'
    err = '\n***  '.join(t[-3:]).replace('"','').replace(' File ', '')
    err = err.replace(', line',':')
    Log("Traceback", '\n'.join(t[:-3]) + '\n\n\n***\n*** ' + err + '\n***\n\n')

    os._exit(4)

def Set_Thread_Label(s):
    global log_next_thread_id
    with log_lock:
        threading.current_thread().__name__ = "%d%s" \
            % (log_next_thread_id, s)
        log_next_thread_id += 1


class Handler(BaseHTTPServer.BaseHTTPRequestHandler):

    def do_GET(self):
        Set_Thread_Label(self.path + "[get]")
        try:
            Log("HTTP", "PATH='%s'" % self.path)
            with open('static' + self.path) as f:
                data = f.read()
            Log("Static", "DATA='%s'" % data)
            self.send_response(200)
            self.send_header("Content-type", "text/html")
            self.end_headers()
            self.wfile.write(data)
        except:
            Log_Traceback()

    def do_POST(self):
        Set_Thread_Label(self.path + "[post]")
        try:
            length = int(self.headers.getheader('content-length'))
            req   = self.rfile.read(length)
            Log("HTTP", "PATH='%s'" % self.path)
            Log("URL", "request data = %s" % req)
            req = json.loads(req)
            response = {'req': req}
            response = json.dumps(response)
            Log("URL", "response data = %s" % response)
            self.send_response(200)
            self.send_header("Content-type", "application/json")
            self.send_header("content-length", str(len(response)))
            self.end_headers()
            self.wfile.write(response)
        except:
            Log_Traceback()


# Create ONE socket.
addr = ('', 8000)
sock = socket.socket (socket.AF_INET, socket.SOCK_STREAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind(addr)
sock.listen(5)

# Launch 100 listener threads.
class Thread(threading.Thread):
    def __init__(self, i):
        threading.Thread.__init__(self)
        self.i = i
        self.daemon = True
        self.start()
    def run(self):
        httpd = BaseHTTPServer.HTTPServer(addr, Handler, False)

        # Prevent the HTTP server from re-binding every handler.
        # https://stackoverflow.com/questions/46210672/
        httpd.socket = sock
        httpd.server_bind = self.server_close = lambda self: None

        httpd.serve_forever()
[Thread(i) for i in range(10)]
time.sleep(9e9)

Nhật ký bảng điều khiển (chrome):

HELLO
hello.html:14 {"req": {"value": "value"}}
hello.html:16 
{req: {…}}
req
:
{value: "value"}
__proto__
:
Object

Nhật ký bảng điều khiển (firefox):

GET 
http://XXXXX:8000/hello.html [HTTP/1.0 200 OK 0ms]
POST 
XHR 
http://XXXXX:8000/postman [HTTP/1.0 200 OK 0ms]
HELLO hello.html:13:3
{"req": {"value": "value"}} hello.html:14:3
Object { req: Object }

Nhật ký bảng điều khiển (Cạnh):

HTML1300: Navigation occurred.
hello.html
HTML1527: DOCTYPE expected. Consider adding a valid HTML5 doctype: "<!DOCTYPE html>".
hello.html (1,1)
Current window: XXXXX/hello.html
HELLO
hello.html (13,3)
{"req": {"value": "value"}}
hello.html (14,3)
[object Object]
hello.html (16,3)
   {
      [functions]: ,
      __proto__: { },
      req: {
         [functions]: ,
         __proto__: { },
         value: "value"
      }
   }

Nhật ký Python:

HTTP 8/postman[post]: PATH='/postman'
URL 8/postman[post]: request data = {"value":"value"}
URL 8/postman[post]: response data = {"req": {"value": "value"}}

8

Có một phương pháp dễ dàng để bọc dữ liệu của bạn và gửi nó đến máy chủ như thể bạn đang gửi một biểu mẫu HTML bằng cách sử dụng POST. bạn có thể làm điều đó bằng cách sử dụng FormDatađối tượng như sau:

data = new FormData()
data.set('Foo',1)
data.set('Bar','boo')

let request = new XMLHttpRequest();
request.open("POST", 'some_url/', true);
request.send(data)

bây giờ bạn có thể xử lý dữ liệu ở phía máy chủ giống như cách bạn xử lý các Biểu mẫu HTML được giới thiệu lại.

Thông tin bổ sung

Bạn không nên đặt tiêu đề Kiểu nội dung khi gửi FormData vì trình duyệt sẽ đảm nhiệm việc đó.


❗️ FormDatasẽ tạo ra một yêu cầu hình thức nhiều phần dữ liệu chứ không phải là một application/x-www-form-urlencodedyêu cầu
ccpizza

@ccpizza - cảm ơn bạn đã làm rõ. Vì OP không đề cập đến loại dữ liệu nào sẽ được POST-ed, tôi nghĩ rằng FormData là cách thích hợp nhất để trả lời.
Armin Hemati Nik

7

hoa tiêu.sendBeacon ()

Nếu bạn chỉ cần POSTdữ liệu và không yêu cầu phản hồi từ máy chủ, giải pháp ngắn nhất sẽ là sử dụng navigator.sendBeacon():

const data = JSON.stringify({
  example_1: 123,
  example_2: 'Hello, world!',
});

navigator.sendBeacon('example.php', data);

1
Không thể thực thi 'sendBeacon' trên 'Navigator': Beacons chỉ được hỗ trợ qua HTTP (S).
Ali80

navigator.sendBeacontheo ý kiến ​​của tôi không được sử dụng cho mục đích này.
jolivier

5

Bạn có thể sử dụng XMLHttpRequest, tìm nạp API, ...

Nếu bạn muốn sử dụng XMLHttpRequest, bạn có thể làm như sau

var xhr = new XMLHttpRequest();
xhr.open("POST", url, true);
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.send(JSON.stringify({
    name: "Deska",
    email: "deska@gmail.com",
    phone: "342234553"
 }));
xhr.onload = function() {
    var data = JSON.parse(this.responseText);
    console.log(data);
};

Hoặc nếu bạn muốn sử dụng API tìm nạp

fetch(url, {
    method:"POST",
    body: JSON.stringify({
        name: "Deska",
        email: "deska@gmail.com",
        phone: "342234553"
        })
    })
    .then(result => {
        // do something with the result
        console.log("Completed with result:", result);
    });

1

Bạn có biết rằng JavaScript có các phương thức và lib được tích hợp sẵn để tạo biểu mẫu và gửi chúng không?

Tôi đang thấy rất nhiều câu trả lời ở đây, tất cả đều yêu cầu sử dụng thư viện của bên thứ 3 mà tôi nghĩ là quá mức cần thiết.

Tôi sẽ làm như sau trong Javascript thuần túy:

<script>
function launchMyForm()
{
   var myForm = document.createElement("FORM");
   myForm.setAttribute("id","TestForm");
   document.body.appendChild(myForm);

// this will create a new FORM which is mapped to the Java Object of myForm, with an id of TestForm. Equivalent to: <form id="TestForm"></form>

   var myInput = document.createElement("INPUT");
   myInput.setAttribute("id","MyInput");
   myInput.setAttribute("type","text");
   myInput.setAttribute("value","Heider");
   document.getElementById("TestForm").appendChild(myInput);

// This will create an INPUT equivalent to: <INPUT id="MyInput" type="text" value="Heider" /> and then assign it to be inside the TestForm tags. 
}
</script>

Bằng cách này (A) bạn không cần phải dựa vào bên thứ 3 để thực hiện công việc. (B) Tất cả được tích hợp sẵn cho tất cả các trình duyệt, (C) nhanh hơn, (D) nó hoạt động, thoải mái dùng thử.

Tôi hi vọng cái này giúp được. H

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.