Reines JavaScript POST-Daten ohne Formular senden

138

Gibt es eine Möglichkeit, Daten mit der POST-Methode ohne Formular und ohne Aktualisierung der Seite nur mit reinem JavaScript (nicht mit jQuery $.post()) zu senden ? Vielleicht httprequestoder etwas anderes (kann es jetzt einfach nicht finden)?

John
quelle
1
XMLHttpRequest ist die Antwort ... $. Post verwendet dasselbe unter der Haube.
Chandu
Diese Frage kann Ihnen helfen: [ stackoverflow.com/questions/58217910/… [1]: stackoverflow.com/questions/58217910/…
Jorge del Campo Andrade

Antworten:

138

Sie können es senden und die Daten in den Körper einfügen:

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

Übrigens, um eine Anfrage zu erhalten:

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();
John G.
quelle
2
Wofür ist die wahre boolesche Variable in xhr.open?
Hylle
67

Die Fetch-API [neu zum Zeitpunkt des Schreibens im Jahr 2017] soll GET-Anforderungen vereinfachen, kann aber auch POST-fähig sein.

let data = {element: "barium"};

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

Wenn Sie so faul sind wie ich (oder einfach nur eine Verknüpfung / einen Helfer bevorzugen):

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

// ...

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

Sie können das XMLHttpRequestObjekt wie folgt verwenden:

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

Dieser Code würde Post someStuffzu url. Stellen Sie einfach sicher, dass Ihr XMLHttpRequestObjekt beim Erstellen browserübergreifend kompatibel ist. Es gibt endlose Beispiele dafür.

James Allardice
quelle
1
Könntest du ein Beispiel dafür schreiben someStuff?
FluorescentGreen5
4
someStuff = 'param1 = val1 & param2 = val2 & param3 = val3'
Camel
1
Das ist eine gute Antwort und someStuffkann alles sein, was Sie wollen, auch eine einfache Zeichenfolge. Sie können die Anfrage mit Online-Diensten wie meinem persönlichen Favoriten überprüfen: ( requestb.in )
JamesC
Der application/x-www-form-urlencodedMIME-Typ hat keinen charsetParameter: iana.org/assignments/media-types/application/…
jbg
28

Mit RESTful können Sie auch Daten von einer POST- Anforderung zurückerhalten .

JS (in static / hello.html einfügen, um über Python zu dienen):

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

Python-Server (zum Testen):

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)

Konsolenprotokoll (Chrom):

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

Konsolenprotokoll (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 }

Konsolenprotokoll (Edge):

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

Python-Protokoll:

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

Es gibt eine einfache Methode, um Ihre Daten zu verpacken und an den Server zu senden, als würden Sie ein HTML-Formular mit senden POST. Sie können dies mit dem FormDataObjekt wie folgt tun :

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

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

Jetzt können Sie die Daten auf der Serverseite genauso behandeln, wie Sie mit reugulären HTML-Formularen umgehen.

Zusätzliche Information

Es wird empfohlen, beim Senden von FormData keinen Content-Type-Header festzulegen, da sich der Browser darum kümmert.

Armin Hemati Nik
quelle
❗️ FormDataerstellt eine mehrteilige Formularanforderung anstelle einer application/x-www-form-urlencodedAnforderung
ccpizza
@ccpizza - danke für die Klarstellung. Da das OP nicht erwähnt hat, welcher Datentyp POST-bearbeitet werden soll, halte ich FormData für die am besten geeignete Antwort.
Armin Hemati Nik
7

navigator.sendBeacon ()

Wenn Sie lediglich POSTDaten benötigen und keine Antwort vom Server benötigen, ist die kürzeste Lösung die Verwendung von navigator.sendBeacon():

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

navigator.sendBeacon('example.php', data);
Grant Miller
quelle
1
'SendBeacon' konnte in 'Navigator' nicht ausgeführt werden: Beacons werden nur über HTTP (S) unterstützt.
Ali80
navigator.sendBeaconist meiner Meinung nach nicht für diesen Zweck gedacht.
Jolivier
5

Sie können XMLHttpRequest verwenden, API abrufen, ...

Wenn Sie XMLHttpRequest verwenden möchten, können Sie Folgendes tun

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

Oder wenn Sie die Abruf-API verwenden möchten

fetch(url, {
    method:"POST",
    body: JSON.stringify({
        name: "Deska",
        email: "[email protected]",
        phone: "342234553"
        })
    })
    .then(result => {
        // do something with the result
        console.log("Completed with result:", result);
    });
Wunsch Kaleba
quelle
1

Wussten Sie, dass JavaScript über integrierte Methoden und Bibliotheken verfügt, mit denen Formulare erstellt und gesendet werden können?

Ich sehe hier viele Antworten, die alle darum bitten, eine Bibliothek von Drittanbietern zu verwenden, was ich für einen Overkill halte.

Ich würde folgendes in reinem Javascript tun:

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

Auf diese Weise (A) müssen Sie sich nicht auf Dritte verlassen, um die Arbeit zu erledigen. (B) Es ist alles in allen Browsern integriert, (C) schneller, (D) es funktioniert, Sie können es gerne ausprobieren.

Ich hoffe das hilft. H.

Heider Sati
quelle