Kirim data POST menggunakan XMLHttpRequest

526

Saya ingin mengirim beberapa data menggunakan XMLHttpRequest dalam JavaScript.

Katakanlah saya memiliki formulir berikut dalam HTML:

<form name="inputform" action="somewhere" method="post">
    <input type="hidden" value="person" name="user">
    <input type="hidden" value="password" name="pwd">
    <input type="hidden" value="place" name="organization">
    <input type="hidden" value="key" name="requiredkey">
</form>

Bagaimana saya bisa menulis yang setara menggunakan XMLHttpRequest di JavaScript?

Jack Greenhill
sumber

Jawaban:

748

Kode di bawah ini menunjukkan cara melakukan ini.

var http = new XMLHttpRequest();
var url = 'get_data.php';
var params = 'orem=ipsum&name=binny';
http.open('POST', url, true);

//Send the proper header information along with the request
http.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');

http.onreadystatechange = function() {//Call a function when the state changes.
    if(http.readyState == 4 && http.status == 200) {
        alert(http.responseText);
    }
}
http.send(params);
Ed Heal
sumber
46
Apakah mungkin untuk mengirim objek paramsdaripada string seperti di jQuery?
Vadorequest
4
Tidak, tetapi komentar @ Vadorequest menyebutkan jQuery - ia bertanya apakah mungkin untuk mengirimkan data "seperti jQuery". Saya menyebutkan bagaimana saya pikir jQuery melakukannya dan dengan demikian, bagaimana Anda bisa mencapai ini.
Dan Pantry
11
@EdHeal, Connectiondan Content-Lengthheader tidak dapat diatur. Itu akan mengatakan "Menolak untuk mengatur judul" panjang konten "" yang tidak aman. Lihat stackoverflow.com/a/2624167/632951
Pacerier
76
Catatan: setRequestHeader () setelah open (). Butuh waktu satu jam, semoga komentar ini menyelamatkan seseorang selama satu jam;)
Kevin
4
apakah mungkin mengirim application/jsonpermintaan?
270
var xhr = new XMLHttpRequest();
xhr.open('POST', 'somewhere', true);
xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
xhr.onload = function () {
    // do something to response
    console.log(this.responseText);
};
xhr.send('user=person&pwd=password&organization=place&requiredkey=key');

Atau jika Anda dapat mengandalkan dukungan browser Anda dapat menggunakan FormData :

var data = new FormData();
data.append('user', 'person');
data.append('pwd', 'password');
data.append('organization', 'place');
data.append('requiredkey', 'key');

var xhr = new XMLHttpRequest();
xhr.open('POST', 'somewhere', true);
xhr.onload = function () {
    // do something to response
    console.log(this.responseText);
};
xhr.send(data);
uKolka
sumber
4
FormData mengambil elemen form sebagai argumen konstruktornya, tidak perlu menambahkan nilai secara perorangan
Juan Mendes
6
Ya, tetapi pertanyaannya adalah untuk menulis JavaScript yang setara dengan formulir yang disediakan, tidak mengirimkan formulir menggunakan JavaScript.
uKolka
3
Jawaban yang memiliki beberapa suara tetapi ditandai dengan benar menggunakan dua header tambahan: http.setRequestHeader("Content-length", params.length);dan http.setRequestHeader("Connection", "close");. Apakah mereka dibutuhkan? Apakah mungkin hanya diperlukan di browser tertentu? (Ada komentar di halaman lain yang mengatakan bahwa pengaturan tajuk Panjang Konten adalah "apa yang dibutuhkan")
Darren Cook
@Darren Cook bergantung pada Implementasi. Dari pengalaman saya, peramban utama menetapkan 'Panjang konten' (diperlukan) secara otomatis dari data yang Anda berikan. Header 'Sambungan' default ke 'tetap-hidup' dalam kebanyakan kasus, yang membuat sambungan terbuka untuk sementara waktu sehingga permintaan berikutnya tidak perlu membangun kembali koneksi lagi seperti dalam kasus 'tutup'. Anda dapat mencoba cuplikan itu di konsol, menggunakan URL halaman saat ini dan memeriksa header permintaan menggunakan alat atau wireshark browser .
uKolka
4
@ uKolka harus dicatat pada balasan daripada dengan solusi kedua Anda permintaan Content-Typeberubah secara otomatis multipart/form-data. Ini memiliki implikasi serius pada sisi server dan bagaimana informasi diakses di sana.
AxeEffect
84

Gunakan JavaScript modern!

Saya sarankan melihat ke dalam fetch. Ini setara dengan ES5 dan menggunakan Janji. Ini jauh lebih mudah dibaca dan mudah disesuaikan.

const url = "http://example.com";
fetch(url, {
    method : "POST",
    body: new FormData(document.getElementById("inputform")),
    // -- or --
    // body : JSON.stringify({
        // user : document.getElementById('user').value,
        // ...
    // })
}).then(
    response => response.text() // .json(), etc.
    // same as function(response) {return response.text();}
).then(
    html => console.log(html)
);

Di Node.js, Anda harus mengimpor fetchmenggunakan:

const fetch = require("node-fetch");

Jika Anda ingin menggunakannya secara sinkron (tidak berfungsi dalam cakupan teratas):

const json = await fetch(url, optionalOptions)
  .then(response => response.json()) // .text(), etc.
  .catch((e) => {});

Info lebih lanjut:

Dokumentasi Mozilla

Dapatkah Saya Menggunakan (95% Mar 2020)

David Walsh Tutorial

Gibolt
sumber
4
Anda harus menghindari menggunakan Janji dan panah gemuk untuk hal-hal yang sangat penting bagi fungsionalitas halaman web ini, karena banyak perangkat tidak memiliki browser yang mendukung fitur-fitur ini.
Dmitry
8
Janji tertutup 90%. Saya menambahkan function()contoh jika Anda tidak suka =>. Anda harus benar-benar menggunakan JS modern untuk memudahkan pengalaman pengembang. Khawatir tentang persentase kecil orang yang terjebak pada IE tidak layak kecuali Anda adalah perusahaan besar
Gibolt
4
Panah gemuk juga tidak berfungsi dengan thiskata kunci. Saya suka menyebutkan itu, tapi saya juga diam-diam membenci orang yang menggunakan this, dan arsitektur warisan bukan fungsi pabrik. Maafkan saya, saya simpul.
agm1984
3
Saya menghindari thisseperti wabah juga, dan harus ada yang membaca this.
Gibolt
2
Jika khawatir tentang kompatibilitas ... Google es6 transpiler ... stackoverflow.com/questions/40205547/… . Tulis itu sederhana. Menyebarkannya kompatibel. 1 hindari this.
TamusJRoyce
35

Penggunaan minimal FormDatauntuk mengirimkan permintaan AJAX

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=Edge, chrome=1"/>
<script>
"use strict";
function submitForm(oFormElement)
{
  var xhr = new XMLHttpRequest();
  xhr.onload = function(){ alert (xhr.responseText); } // success case
  xhr.onerror = function(){ alert (xhr.responseText); } // failure case
  xhr.open (oFormElement.method, oFormElement.action, true);
  xhr.send (new FormData (oFormElement));
  return false;
}
</script>
</head>

<body>
<form method="post" action="somewhere" onsubmit="return submitForm(this);">
  <input type="hidden" value="person"   name="user" />
  <input type="hidden" value="password" name="pwd" />
  <input type="hidden" value="place"    name="organization" />
  <input type="hidden" value="key"      name="requiredkey" />
  <input type="submit" value="post request"/>
</form>
</body>
</html>

Catatan

  1. Ini tidak sepenuhnya menjawab pertanyaan OP karena mengharuskan pengguna untuk mengklik untuk mengirim permintaan. Tetapi ini mungkin berguna bagi orang yang mencari solusi sederhana semacam ini.

  2. Contoh ini sangat sederhana dan tidak mendukung GETmetode ini. Jika Anda tertarik dengan contoh yang lebih canggih, silakan lihat dokumentasi MDN yang luar biasa . Lihat juga jawaban serupa tentang XMLHttpRequest to Post HTML Form .

  3. Batasan solusi ini: Seperti yang ditunjukkan oleh Justin Blank dan Thomas Munk (lihat komentar mereka), FormDatatidak didukung oleh IE9 dan lebih rendah, dan browser default pada Android 2.3.

olibre
sumber
1
Satu-satunya hal tentang ini adalah saya pikir FormData tidak tersedia di IE 9, jadi itu tidak akan dapat digunakan untuk banyak orang tanpa polyfill. developer.mozilla.org/en-US/docs/Web/API/FormData
Justin Blank
Terima kasih @ThomasMunk untuk tautan Anda :-) Kami melihat bahwa FormDatadidukung oleh banyak browser kecuali IE9 dan Android 2.3 (dan OperaMini tetapi yang terakhir ini tidak banyak digunakan). Cheers ;-)
olibre
2
Solusi elegan, tetapi Anda harus menentukan onsubmit="return submitForm(this);"jika tidak, pengguna akan diarahkan ke URL dalam permintaan.
Vic
Terima kasih @Vic atas kontribusi Anda, saya telah memperbarui jawabannya. Cheers ;-)
olibre
1
Saya tidak begitu berpengalaman dengan pengembangan web. Saya telah mengetahui bahwa permintaan POST memang dikirim ketika Anda kembali false. Jika truedikembalikan, permintaan POST asli (tidak diinginkan) akan dikirimkan! Jawaban Anda benar, maaf atas kebingungan.
Markus L
30

Berikut ini adalah solusi lengkap dengan application-json:

// Input values will be grabbed by ID
<input id="loginEmail" type="text" name="email" placeholder="Email">
<input id="loginPassword" type="password" name="password" placeholder="Password">

// return stops normal action and runs login()
<button onclick="return login()">Submit</button>

<script>
    function login() {
        // Form fields, see IDs above
        const params = {
            email: document.querySelector('#loginEmail').value,
            password: document.querySelector('#loginPassword').value
        }

        const http = new XMLHttpRequest()
        http.open('POST', '/login')
        http.setRequestHeader('Content-type', 'application/json')
        http.send(JSON.stringify(params)) // Make sure to stringify
        http.onload = function() {
            // Do whatever with response
            alert(http.responseText)
        }
    }
</script>

Pastikan bahwa Backend API Anda dapat mengurai JSON.

Misalnya, di Express JS:

import bodyParser from 'body-parser'
app.use(bodyParser.json())
agm1984
sumber
1
Hebat, tetapi jangan gunakan nilai 'salah' untuk parameter async di XMLHttpRequest.open - sudah tidak digunakan lagi dan akan memberikan peringatan
johnnycardy
Haruskah kita menaruh true di sana atau hanya menghilangkan parameter itu? Saya akan memperbarui jawabannya jika Anda dapat menentukan mana yang lebih disukai.
agm1984
1
Seharusnya default ke true tapi saya tidak tahu apakah semua browser menghormatinya
johnnycardy
Mengingat default true, saya akan menghapusnya dari contoh dan menjatuhkan URL ini untuk penelitian: developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/open
agm1984
1
Saya suka itu lebih baik karena itu masuk akal dan satu detail kurang untuk seseorang untuk memulai. Terima kasih telah menyoroti ini.
agm1984
25

TIDAK PERLU PLUGIN!

Pilih kode di bawah ini dan seret ke dalam BOOKMARK BAR ( jika Anda tidak melihatnya, aktifkan dari Pengaturan Browser ), lalu EDIT tautan itu:

masukkan deskripsi gambar di sini

javascript:var my_params = prompt("Enter your parameters", "var1=aaaa&var2=bbbbb"); var Target_LINK = prompt("Enter destination", location.href); function post(path, params) { var xForm = document.createElement("form"); xForm.setAttribute("method", "post"); xForm.setAttribute("action", path); for (var key in params) { if (params.hasOwnProperty(key)) { var hiddenField = document.createElement("input"); hiddenField.setAttribute("name", key); hiddenField.setAttribute("value", params[key]); xForm.appendChild(hiddenField); } } var xhr = new XMLHttpRequest(); xhr.onload = function () { alert(xhr.responseText); }; xhr.open(xForm.method, xForm.action, true); xhr.send(new FormData(xForm)); return false; } parsed_params = {}; my_params.split("&").forEach(function (item) { var s = item.split("="), k = s[0], v = s[1]; parsed_params[k] = v; }); post(Target_LINK, parsed_params); void(0);

Itu saja! Sekarang Anda dapat mengunjungi situs web apa pun, dan klik tombol itu di BAR BOOKMARK !


CATATAN:

Metode di atas mengirim data menggunakan XMLHttpRequestmetode, jadi, Anda harus berada di domain yang sama saat memicu skrip. Itu sebabnya saya lebih suka mengirim data dengan simulasi PENGIRIMAN FORMULIR, yang dapat mengirim kode ke domain apa pun - di sini adalah kode untuk itu:

 javascript:var my_params=prompt("Enter your parameters","var1=aaaa&var2=bbbbb"); var Target_LINK=prompt("Enter destination", location.href); function post(path, params) {   var xForm= document.createElement("form");   xForm.setAttribute("method", "post");   xForm.setAttribute("action", path); xForm.setAttribute("target", "_blank");   for(var key in params) {   if(params.hasOwnProperty(key)) {        var hiddenField = document.createElement("input");      hiddenField.setAttribute("name", key);      hiddenField.setAttribute("value", params[key]);         xForm.appendChild(hiddenField);     }   }   document.body.appendChild(xForm);  xForm.submit(); }   parsed_params={}; my_params.split("&").forEach(function(item) {var s = item.split("="), k=s[0], v=s[1]; parsed_params[k] = v;}); post(Target_LINK, parsed_params); void(0); 
T.Todua
sumber
Untuk Mozilla, bisakah saya melakukan sesuatu yang mirip dengan ini?
Saya tidak dan saya tidak bisa: | Saya tidak punya 125 repetisi: | Dan jika Anda melihat profil saya, Anda akan melihat saya memiliki 136 suara: | Bahkan setelah saya mendapat izin untuk downvote, saya akan menghindarinya kecuali itu perlu: |
18
Dan pertanyaan Anda benar-benar tidak menjawab apa yang diminta OP. BookMarking Permintaan HTTP ...!? Saya tidak melihat poin apa pun yang berhubungan XmlHttpRequestdengan jawaban Anda: |
2
luar biasa. hanya ingin beberapa hubungan saat meninjau karena itu adalah jawaban. sekarang ini adalah jawaban plus tip gr8 untuk semua yang mampir. saya telah mengembalikan suara. Cheers
Iceman
5

Saya menghadapi masalah yang sama, menggunakan pos yang sama dan dan tautan ini telah saya atasi masalah saya.

 var http = new XMLHttpRequest();
 var url = "MY_URL.Com/login.aspx";
 var params = 'eid=' +userEmailId+'&amp;pwd='+userPwd

 http.open("POST", url, true);

 // Send the proper header information along with the request
 //http.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
 //http.setRequestHeader("Content-Length", params.length);// all browser wont support Refused to set unsafe header "Content-Length"
 //http.setRequestHeader("Connection", "close");//Refused to set unsafe header "Connection"

 // Call a function when the state 
 http.onreadystatechange = function() {
    if(http.readyState == 4 && http.status == 200) {
        alert(http.responseText);
    }
 }
 http.send(params);

Tautan ini telah menyelesaikan informasi.

Laxman G
sumber
4
var util = {
    getAttribute: function (dom, attr) {
        if (dom.getAttribute !== undefined) {
            return dom.getAttribute(attr);
        } else if (dom[attr] !== undefined) {
            return dom[attr];
        } else {
            return null;
        }
    },
    addEvent: function (obj, evtName, func) {
        //Primero revisar attributos si existe o no.
        if (obj.addEventListener) {
            obj.addEventListener(evtName, func, false);

        } else if (obj.attachEvent) {
            obj.attachEvent(evtName, func);
        } else {
            if (this.getAttribute("on" + evtName) !== undefined) {
                obj["on" + evtName] = func;
            } else {
                obj[evtName] = func;
            }

        }

    },
    removeEvent: function (obj, evtName, func) {
        if (obj.removeEventListener) {
            obj.removeEventListener(evtName, func, false);
        } else if (obj.detachEvent) {
            obj.detachEvent(evtName, func);
        } else {
            if (this.getAttribute("on" + evtName) !== undefined) {
                obj["on" + evtName] = null;
            } else {
                obj[evtName] = null;
            }
        }

    },
    getAjaxObject: function () {
        var xhttp = null;
        //XDomainRequest
        if ("XMLHttpRequest" in window) {
            xhttp = new XMLHttpRequest();
        } else {
            // code for IE6, IE5
            xhttp = new ActiveXObject("Microsoft.XMLHTTP");
        }
        return xhttp;
    }

};

//START CODE HERE.

var xhr = util.getAjaxObject();

var isUpload = (xhr && ('upload' in xhr) && ('onprogress' in xhr.upload));

if (isUpload) {
    util.addEvent(xhr, "progress", xhrEvt.onProgress());
    util.addEvent(xhr, "loadstart", xhrEvt.onLoadStart);
    util.addEvent(xhr, "abort", xhrEvt.onAbort);
}

util.addEvent(xhr, "readystatechange", xhrEvt.ajaxOnReadyState);

var xhrEvt = {
    onProgress: function (e) {
        if (e.lengthComputable) {
            //Loaded bytes.
            var cLoaded = e.loaded;
        }
    },
    onLoadStart: function () {
    },
    onAbort: function () {
    },
    onReadyState: function () {
        var state = xhr.readyState;
        var httpStatus = xhr.status;

        if (state === 4 && httpStatus === 200) {
            //Completed success.
            var data = xhr.responseText;
        }

    }
};
//CONTINUE YOUR CODE HERE.
xhr.open('POST', 'mypage.php', true);
xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');


if ('FormData' in window) {
    var formData = new FormData();
    formData.append("user", "aaaaa");
    formData.append("pass", "bbbbb");

    xhr.send(formData);

} else {

    xhr.send("?user=aaaaa&pass=bbbbb");
}
toto
sumber
1
Halo Hugo, Kode ini untuk mengirim data atau file dengan unggahan progres jika browser mendukungnya. termasuk semua kemungkinan acara dan browser kompatibilitas. Itu mencoba menggunakan objek kelas paling baru dari browser. Itu membantu Anda?
toto
2

Cobalah untuk menggunakan objek json, bukan formdata. di bawah ini adalah kode yang berfungsi untuk saya. formdata juga tidak bekerja untuk saya, maka saya datang dengan solusi ini.

var jdata = new Object();
jdata.level = levelVal; // level is key and levelVal is value
var xhttp = new XMLHttpRequest();
xhttp.open("POST", "http://MyURL", true);
xhttp.setRequestHeader('Content-Type', 'application/json');
xhttp.send(JSON.stringify(jdata));

xhttp.onreadystatechange = function() {
    if (this.readyState == 4 && this.status == 200) {
      console.log(this.responseText);
    }
}
Cuci Otak
sumber
1

Hanya untuk pembaca fitur yang menemukan pertanyaan ini. Saya menemukan bahwa jawaban yang diterima berfungsi dengan baik selama Anda memiliki jalur yang diberikan, tetapi jika Anda membiarkannya kosong itu akan gagal di IE. Inilah yang saya pikirkan:

function post(path, data, callback) {
    "use strict";
    var request = new XMLHttpRequest();

    if (path === "") {
        path = "/";
    }
    request.open('POST', path, true);
    request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
    request.onload = function (d) {
        callback(d.currentTarget.response);
    };
    request.send(serialize(data));
}

Anda dapat melakukannya seperti ini:

post("", {orem: ipsum, name: binny}, function (response) {
    console.log(respone);
})
Sebastian Td
sumber
1

Ada beberapa duplikat yang menyentuh ini, dan tidak ada yang benar-benar menguraikannya. Saya akan meminjam contoh jawaban yang diterima untuk menggambarkan

http.open('POST', url, true);
http.send('lorem=ipsum&name=binny');

Saya terlalu menyederhanakan ini (saya menggunakan http.onload(function() {})alih-alih metodologi yang lebih tua dari jawaban itu) demi ilustrasi. Jika Anda menggunakan apa adanya, Anda akan menemukan server Anda mungkin mengartikan tubuh POST sebagai string dan bukan key=valueparameter aktual (mis. PHP tidak akan menampilkan $_POSTvariabel apa pun ). Anda harus melewati form header untuk mendapatkan itu, dan lakukan itu sebelumnyahttp.send()

http.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');

Jika Anda menggunakan JSON dan bukan data yang disandikan URL, kirimkan application/jsonsaja

Machavity
sumber
1

Ini membantu saya karena saya hanya ingin menggunakan xmlHttpRequestdan memposting objek sebagai data formulir:

function sendData(data) {
  var XHR = new XMLHttpRequest();
  var FD  = new FormData();

  // Push our data into our FormData object
  for(name in data) {
    FD.append(name, data[name]);
  }

  // Set up our request
  XHR.open('POST', 'https://example.com/cors.php');

  // Send our FormData object; HTTP headers are set automatically
  XHR.send(FD);
}

https://developer.mozilla.org/en-US/docs/Learn/HTML/Forms/Sending_forms_through_JavaScript

M3RS
sumber