Saf JavaScript POST Verilerini Form Olmadan Gönderin


141

POST yöntemini kullanarak form olmadan ve sayfayı yalnızca salt JavaScript kullanarak (jQuery değil $.post()) yenilemeden veri göndermenin bir yolu var mı ? Belki httprequestveya başka bir şey (şimdi bulamıyorum)?


1
XMLHttpRequest cevaptır ... $. Post, başlık altında aynı şeyi kullanır.
Chandu

Yanıtlar:


140

Gönderebilir ve verileri gövdeye ekleyebilirsiniz:

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

Bu arada, istek almak için:

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
Xhr.open'daki gerçek boole değişkeni ne için?
Hylle


68

[2017'de yazıldığı sırada new-ish] Fetch API , GET isteklerini kolaylaştırmayı amaçlıyor, ancak POST da yapabiliyor.

let data = {element: "barium"};

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

Benim kadar tembelseniz (veya sadece bir kısayolu / yardımcıyı tercih ediyorsanız):

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

// ...

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

54

XMLHttpRequestNesneyi şu şekilde kullanabilirsiniz :

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

Bu kod sonrası olacaktır someStuffiçin url. XMLHttpRequestNesnenizi oluşturduğunuzda, tarayıcılar arası uyumlu olacağından emin olun . Bunun nasıl yapılacağına dair sonsuz örnekler var.


1
bir örnek yazabilir misin someStuff?
FluorescentGreen5

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

1
Bu iyi bir cevap ve someStuffbasit bir dizge bile istediğiniz herhangi bir şey olabilir. Eğer böyle benim kişisel favori olarak çevrimiçi hizmetleri kullanarak isteği kontrol edebilirsiniz: ( requestb.in )
JamesC

application/x-www-form-urlencodedMIME türü bir yok charsetparametresi: iana.org/assignments/media-types/application/...
jbg

29

Ayrıca RESTful , bir POST isteğinden verileri geri almanızı sağlar .

JS (Python aracılığıyla sunmak için static / hello.html yazın):

<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 sunucusu (test için):

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)

Konsol günlüğü (krom):

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

Konsol günlüğü (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 }

Konsol günlüğü (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 günlüğü:

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

8

Kullanarak bir HTML formu gönderiyormuşsunuz gibi verilerinizi sarmalamanın ve sunucuya göndermenin kolay bir yöntemi vardır POST. bunu FormDataaşağıdaki gibi nesne kullanarak yapabilirsiniz :

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

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

artık, tıpkı reugular HTML Formları ile yaptığınız gibi sunucu tarafındaki verileri işleyebilirsiniz.

İlave bilgi

Tarayıcı bunu halledeceği için FormData'yı gönderirken Content-Type başlığını ayarlamamanız tavsiye edilir.


❗️ FormDatabir yerine çok bölümlü form isteği yaratacak application/x-www-form-urlencodedistek
ccpizza

@ccpizza - açıklama için teşekkür ederim. OP, hangi tür verilerin POST edileceğinden bahsetmediğinden, FormData'nın yanıtlamanın en uygun yolu olduğunu düşünüyorum.
Armin Hemati Nik

7

navigator.sendBeacon ()

Yalnızca POSTverilere ihtiyacınız varsa ve sunucudan yanıt almanız gerekmiyorsa , en kısa çözüm aşağıdakileri kullanmak olacaktır navigator.sendBeacon():

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

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

1
'Navigator'da' sendBeacon 'yürütülemedi: İşaretler yalnızca HTTP (S) üzerinden desteklenir.
Ali80

navigator.sendBeaconbence bu amaç için kullanılması amaçlanmamıştır.
jolivier

6

XMLHttpRequest, fetch API, ...

kullanabilirsiniz. XMLHttpRequest'i kullanmak istiyorsanız aşağıdakileri yapabilirsiniz

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

Ya da getirme API'sini kullanmak istiyorsanız

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

2

JavaScript'in formları oluşturmak ve göndermek için yerleşik yöntemlere ve kitaplıklara sahip olduğunu biliyor muydunuz?

Burada çok fazla yanıt görüyorum, hepsi de bir 3. parti kitaplığı kullanmak istiyor, ki bunun aşırı bir şey olduğunu düşünüyorum.

Aşağıdakileri saf Javascript ile yapardım:

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

Bu şekilde (A) işi yapmak için 3. şahıslara güvenmeniz gerekmez. (B) Hepsi tüm tarayıcılarda yerleşiktir, (C) daha hızlıdır, (D) çalışır, denemekten çekinmeyin.

Umarım bu yardımcı olur. 'H

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.