JavaScript pur Envoyer des données POST sans formulaire


141

Existe-t-il un moyen d'envoyer des données à l'aide de la méthode POST sans formulaire et sans actualiser la page en utilisant uniquement du JavaScript pur (pas jQuery $.post())? Peut httprequest- être ou autre chose (je ne peux pas le trouver maintenant)?


1
XMLHttpRequest est la réponse ... $. Post utilise la même chose sous le capot.
Chandu

Réponses:


140

Vous pouvez l'envoyer et insérer les données dans le corps:

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

Au fait, pour obtenir une demande:

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
À quoi sert la vraie variable booléenne dans xhr.open?
Hylle


68

L' API Fetch [nouvelle au moment de la rédaction de cet article en 2017] est destinée à faciliter les requêtes GET, mais elle est également capable de POST.

let data = {element: "barium"};

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

Si vous êtes aussi paresseux que moi (ou préférez simplement un raccourci / aide):

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

// ...

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

54

Vous pouvez utiliser l' XMLHttpRequestobjet comme suit:

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

Ce code publierait someStuffsur url. Assurez-vous simplement que lorsque vous créez votre XMLHttpRequestobjet, il sera compatible avec tous les navigateurs. Il existe d'innombrables exemples sur la façon de procéder.


1
pourrais-tu écrire un exemple someStuff?
FluorescentGreen5

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

1
C'est une bonne réponse, et someStuffpeut être tout ce que vous voulez, même une simple chaîne. vous pouvez vérifier la demande en utilisant des services en ligne tels que mon favori personnel: ( requestb.in )
JamesC

le application/x-www-form-urlencodedtype MIME n'a pas de charsetparamètre: iana.org/assignments/media-types/application
...

28

De plus, RESTful vous permet de récupérer des données à partir d'une requête POST .

JS (mis dans static / hello.html pour servir via 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>

Serveur Python (pour les tests):

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)

Journal de la console (chrome):

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

Journal de la console (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 }

Journal de la console (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"
      }
   }

Journal 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

Il existe une méthode simple pour envelopper vos données et les envoyer au serveur comme si vous envoyiez un formulaire HTML en utilisant POST. vous pouvez le faire en utilisant un FormDataobjet comme suit:

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

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

maintenant, vous pouvez gérer les données côté serveur comme vous le faites avec les formulaires HTML réguliers.

Information additionnelle

Il est conseillé de ne pas définir l'en-tête Content-Type lors de l'envoi de FormData car le navigateur s'en chargera.


❗️ FormDatacréera une demande de formulaire en plusieurs parties plutôt qu'une application/x-www-form-urlencodeddemande
ccpizza

@ccpizza - merci pour la clarification. comme l'OP n'a pas mentionné le type de données à publier, je pense que FormData est le moyen le plus approprié de répondre.
Armin Hemati Nik

7

navigator.sendBeacon ()

Si vous avez simplement besoin de POSTdonnées et que vous n'avez pas besoin d'une réponse du serveur, la solution la plus courte serait d'utiliser navigator.sendBeacon():

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

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

1
Échec de l'exécution de 'sendBeacon' sur 'Navigator': les balises ne sont prises en charge que sur HTTP (S).
Ali80

navigator.sendBeaconn'est pas destiné à être utilisé à cette fin à mon avis.
jolivier le

5

Vous pouvez utiliser XMLHttpRequest, fetch API, ...

Si vous souhaitez utiliser XMLHttpRequest, vous pouvez faire ce qui suit

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

Ou si vous souhaitez utiliser Fetch API

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

Saviez-vous que JavaScript a ses méthodes et bibliothèques intégrées pour créer des formulaires et les soumettre?

Je vois beaucoup de réponses ici demandant toutes d'utiliser une bibliothèque tierce, ce qui, je pense, est exagéré.

Je ferais ce qui suit en Javascript pur:

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

De cette façon (A), vous n'avez pas besoin de compter sur des tiers pour faire le travail. (B) Tout est intégré à tous les navigateurs, (C) plus rapide, (D) cela fonctionne, n'hésitez pas à l'essayer.

J'espère que ça aide. H

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.