JavaScript Murni Kirim Data POST Tanpa Formulir


140

Apakah ada cara untuk mengirim data menggunakan metode POST tanpa formulir dan tanpa menyegarkan halaman hanya menggunakan JavaScript murni (bukan jQuery $.post())? Mungkin httprequestatau yang lainnya (tidak bisa menemukannya sekarang)?


1
XMLHttpRequest adalah jawabannya ... $. Post menggunakan hal yang sama di bawah tenda.
Chandu

Jawaban:


139

Anda dapat mengirimnya dan memasukkan data ke badan:

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

Omong-omong, untuk mendapatkan permintaan:

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
Untuk apa variabel boolean sebenarnya dalam xhr.open?
Hylle


68

Fetch API [new-ish pada saat penulisan pada tahun 2017] dimaksudkan untuk membuat permintaan GET mudah, tetapi juga dapat POST.

let data = {element: "barium"};

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

Jika Anda malas seperti saya (atau lebih suka jalan pintas / pembantu):

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

// ...

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

54

Anda dapat menggunakan XMLHttpRequestobjek sebagai berikut:

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

Kode itu akan dikirim someStuffke url. Pastikan saja ketika Anda membuat XMLHttpRequestobjek Anda , itu akan kompatibel lintas-browser. Ada banyak contoh yang tak ada habisnya tentang bagaimana melakukannya.


1
bisakah Anda menulis contoh untuk someStuff?
FluorescentGreen5

4
someStuff = 'param1 = val1 & param2 = val2 & param3 = val3'
Camel

1
Itu jawaban yang bagus, dan someStuffbisa menjadi apa pun yang Anda inginkan bahkan string sederhana. Anda dapat memeriksa permintaan menggunakan layanan online seperti favorit pribadi saya: ( requestb.in )
JamesC

yang application/x-www-form-urlencodedtipe MIME tidak memiliki charsetparameter: iana.org/assignments/media-types/application/...
JBG

28

Selain itu, RESTful memungkinkan Anda mendapatkan data kembali dari permintaan POST .

JS (masukkan static / hello.html untuk melayani melalui 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>

Server Python (untuk pengujian):

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)

Log konsol (chrome):

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

Log konsol (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 }

Log konsol (Tepi):

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"
      }
   }

Log 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

Ada metode mudah untuk membungkus data Anda dan mengirimkannya ke server seolah-olah Anda mengirim formulir HTML menggunakan POST. Anda dapat melakukannya menggunakan FormDataobjek sebagai berikut:

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

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

sekarang Anda dapat menangani data di sisi server seperti cara Anda menangani Formulir HTML reugular.

Informasi tambahan

Disarankan bahwa Anda tidak boleh mengatur header Tipe Konten saat mengirim FormData karena browser akan mengurusnya.


❗️ FormDataakan membuat permintaan bentuk multi-bagian alih-alih application/x-www-form-urlencodedpermintaan
ccpizza

@ccpizza - terima kasih atas klarifikasi. karena OP tidak menyebutkan tipe data mana yang harus POST-ed, saya pikir FormData adalah cara yang paling tepat untuk menjawab.
Armin Hemati Nik

7

navigator.sendBeacon ()

Jika Anda hanya perlu POSTdata dan tidak memerlukan respons dari server, solusi terpendek adalah menggunakan navigator.sendBeacon():

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

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

1
Gagal menjalankan 'sendBeacon' di 'Navigator': Beacon hanya didukung melalui HTTP (S).
Ali80

navigator.sendBeacontidak dimaksudkan untuk digunakan untuk tujuan ini menurut saya.
Jolivier

5

Anda dapat menggunakan XMLHttpRequest, fetch API, ...

Jika Anda ingin menggunakan XMLHttpRequest, Anda dapat melakukan hal berikut

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);
};

Atau jika Anda ingin menggunakan API ambil

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

Tahukah Anda bahwa JavaScript memiliki metode dan lib bawaan untuk membuat formulir dan mengirimkannya?

Saya melihat banyak balasan di sini semua meminta untuk menggunakan perpustakaan pihak ke-3 yang menurut saya berlebihan.

Saya akan melakukan hal berikut dalam Javascript murni:

<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>

Dengan cara ini (A) Anda tidak perlu bergantung pada pihak ketiga untuk melakukan pekerjaan itu. (B) Semuanya built-in untuk semua browser, (C) lebih cepat, (D) berfungsi, jangan ragu untuk mencobanya.

Saya harap ini membantu. H

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.