纯Javascript发送没有表单的帖子数据

Joh*_*ohn 104 javascript post xmlhttprequest http-post httpwebrequest

有没有办法使用post方法发送数据而没有表单,没有刷新页面只使用纯Javascript(不是jQuery $.post())?也许是httprequest或其他东西,现在找不到它.

Joh*_*n G 107

您可以发送它并将数据插入正文:

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

顺便说一下,获取请求:

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();
Run Code Online (Sandbox Code Playgroud)

  • 这是执行请求的旧方法。我强烈建议不要使用此方法并使用“fetch”函数。 (3认同)
  • xhr.open中真正的布尔变量是什么? (2认同)
  • @Hylle异步:https://developer.mozilla.org/zh-CN/docs/Web/API/XMLHttpRequest/open (2认同)

Jam*_*ice 50

您可以XMLHttpRequest按如下方式使用该对象:

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

该代码将发布someStuffurl.只需确保在创建XMLHttpRequest对象时,它将与跨浏览器兼容.有无数的例子说明如何做到这一点.

  • 你能为“someStuff”写一个例子吗? (3认同)
  • someStuff ='param1 = val1&param2 = val2&param3 = val3' (3认同)

Con*_*oad 41

[2017年撰写时的新内容] Fetch API旨在使GET请求变得简单,但它也可以进行POST.

let data = {element: "barium"};

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

如果你像我一样懒(或者只是喜欢快捷方式/助手):

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

// ...

post("post/data/here", {element: "osmium"});
Run Code Online (Sandbox Code Playgroud)

  • 由于这个答案很简单,我过早地投票了,而且它不允许我撤回投票。仅当添加标头时发送数据才有效。(headers: {'Accept': 'application/json', 'Content-Type': 'application/json'}) 此外,除非您在响应上调用 json() 方法,否则接收数据也不起作用,如下所示:res.json(),它恰好返回另一个您必须解开的承诺。最好使用 async/await 并用 wait 解开所有这些承诺。 (2认同)

Des*_*eba 26

你可以使用 XMLHttpRequest, fetch API, ...

如果你想使用 XMLHttpRequest 你可以执行以下操作

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);
};
Run Code Online (Sandbox Code Playgroud)

或者如果你想使用 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);
    }).catch(err => {
        // if any error occured, then catch it here
        console.error(err);
    });
Run Code Online (Sandbox Code Playgroud)


per*_*oud 24

此外,REST风格让你得到的数据POST请求.

JS(放入static/hello.html通过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>
Run Code Online (Sandbox Code Playgroud)

Python服务器(用于测试):

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)
Run Code Online (Sandbox Code Playgroud)

控制台日志(chrome):

HELLO
hello.html:14 {"req": {"value": "value"}}
hello.html:16 
{req: {…}}
req
:
{value: "value"}
__proto__
:
Object
Run Code Online (Sandbox Code Playgroud)

控制台日志(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 }
Run Code Online (Sandbox Code Playgroud)

控制台日志(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"
      }
   }
Run Code Online (Sandbox Code Playgroud)

Python日志:

HTTP 8/postman[post]: PATH='/postman'
URL 8/postman[post]: request data = {"value":"value"}
URL 8/postman[post]: response data = {"req": {"value": "value"}}
Run Code Online (Sandbox Code Playgroud)


小智 10

有一种简单的方法可以包装数据并将其发送到服务器,就像使用POST. 你可以使用FormData对象来做到这一点,如下所示:

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

let request = new XMLHttpRequest();
request.open("POST", 'some_url/', true);
request.send(data)
Run Code Online (Sandbox Code Playgroud)

现在您可以像处理常规 HTML 表单一样在服务器端处理数据。

附加信息

建议您在发送 FormData 时不要设置 Content-Type 标头,因为浏览器会处理这些。


Hei*_*ati 7

您是否知道 JavaScript 具有创建表单和提交表单的内置方法和库?

我在这里看到很多回复都要求使用 3rd 方库,我认为这有点矫枉过正。

我会在纯 Javascript 中执行以下操作:

<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>
Run Code Online (Sandbox Code Playgroud)

这样 (A) 你不需要依赖 3rd 方来完成这项工作。(B) 所有浏览器都内置了它,(C) 更快,(D) 它可以工作,请随意尝试。

我希望这有帮助。H


OCD*_*Dev 7

这里最受欢迎的答案没有显示如何从 POST 获取数据。此外,当将数据发送到最新版本的 NodeJS 时,流行的“获取”解决方案在最新版本的 Chrome 中不起作用,除非您传递标头并解开 response.json() 承诺。此外,流行的答案不使用 async/await。

这是我能想到的最干净、最完整的解决方案。

async function postJsonData(jsonObject) {
    const response = await fetch("/echo", {
        method: "POST",
        headers: {'Content-Type': 'application/json'},
        body: JSON.stringify(jsonObject)
    });
    
    const actualResponse = await response.json();
}
Run Code Online (Sandbox Code Playgroud)


Gra*_*ler 6

navigator.sendBeacon()

如果您只需要POST数据并且不需要服务器响应,则最短的解决方案是使用navigator.sendBeacon()

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

navigator.sendBeacon('example.php', data);
Run Code Online (Sandbox Code Playgroud)

  • 无法在“导航器”上执行“sendBeacon”:仅通过 HTTP(S) 支持信标。 (2认同)