XMLHttpRequest dan AJAX

Apa itu AJAX?

AJAX merupakan singkatan dari “Asynchronous Javascript and XML”. Secara sederhana, AJAX memungkinkan kita untuk berkomunikasi dengan kode program pada server melalui Javascript. Melalui AJAX, kita dapat memanggil kode pada server melalui URL tertentu, dan menerima data / pesan hasil eksekusi oleh server. Pada awal pengembangan, server mengembalikan data dalam format XML (‘X’ pada AJAX). Pada prakteknya, server dapat mengembalikan data apapun, selaam kode klien mengetahui format yang diberikan. Bahkan pada perkembangan selanjutnya, format JSON menjadi lebih populer dibandingkan XML.

Bagian yang paling menarik dari AJAX ialah bahwa komunikasi dengan server dilakukan secara asinkron (‘A’ pada AJAX). Hal ini berarti kita dapat berkomunikasi dengan server tanpa mengganggu aktivitas atau eksekusi lain pada sisi klien maupun server. Kita bahkan tidak perlu berpindah halaman atau melakukan reload halaman untuk melihat hasil eksekusi kode AJAX.

Jadi, dengan AJAX kita dapat melakukan dua hal berikut:

  1. Mengirimkan perintah kepada server tanpa harus berpindah atau reload halaman.
  2. Menerima data dari server dan kemudian mengolahnya. Data hanya akan dapat diberikan server setelah kita mengirimkan perintah.

Setelah kita menerima dan mengolah data dari server, kita kemudian dapat memperbaharui halaman sesuai dengan kebutuhan. Ingat juga bahwa komunikasi ke server pada teknologi AJAX berjalan satu arah: kita mengirimkan perintah ke server, dan hanya setelah itu server dapat mengirimkan data kembali ke klien. Jika tidak ada pengiriman perintah dari klien, maka server tidak dapat langsung memberikan data ke klien. Hal ini disebabkan oleh sifat dasar dari web yang *stateless*, di mana server tidak menyimpan daftar klien yang sedang terkoneksi dengannya. Tanpa server mengetahi siapa saja yang sedang terkoneksi dengannya, maka ia tidak dapat mengirimkan data kepada klien tersebut.

Keseluruhan fungsi dari AJAX ini dapat dicapai dengan menggunakan objek XMLHttpRequest yang telah disediakan oleh browser. Langsung saja, kita akan melihat bagaimana menggunakan objek ini.

Pembuatan XMLHttpRequest

Objek XMLHttpRequest (selanjutnya dirujuk sebagai xhr saja dalam kode dan nama method) merupakan objek inti untuk melakukan operasi AJAX. Pembuatan objek ini pada browser modern cukup mudah dan jelas:

1
2
3
4
5
6
var xhr;
if (window.XMLHttpRequest) {
    xhr = new XMLHttpRequest();
} else {
    alert("Browser tidak mendukung AJAX");
}

Sayangnya, kode di atas tidak dapat digunakan jika kita harus mendukung browser lama seperti IE6. Jika ingin menggunakan operasi AJAX pada browser lama, kita dapat menggunakan objek alternatif, yaitu ActiveXObject:

1
2
3
4
5
6
7
8
var xhr;
if (window.XMLHttpRequest) { // Chrome, safari, IE7+, Opera, dll
    xhr = new XMLHttpRequest();
} else if (window.ActiveXObject) { // IE5/6
    xhr = new ActiveXObject("Microsoft.XMLHTTP");
} else {
    alert("Browser tidak mendukung AJAX!");
}

Cara kedua yang mendukung browser lama ini tidak disarankan untuk digunakan, karena dapat menambah beban pengujian. Anda lebih disarankan untuk memperbaharui browser anda dibandingkan dengan menggunakan kode di atas. Menggunakan browser lama yang tidak didukung lagi membuka celah kemanan yang sangat besar, ditambah lagi ActiveXObject merupakan objek yang tidak didukung oleh standar Javascript secara resmi.

Mengirimkan Perintah ke Server

Mengirimkan perintah ke server dilakukan melalui protokol HTTP, yang dapat dipanggil menggunakan method xhr.open dan xhr.send dari XMLHttpRequest:

1
2
xhr.open("GET", "http://example.com/ajax/", true);
xhr.send(null);

Method xhr.open digunakan untuk melakukan inisialisasi perintah yang akan kita kirimkan ke server. Parameter yang kita kirimkan ke xhr.open memiliki arti tersendiri:

  • Parameter pertama dari xhr.open menentukan HTTP Request Method yang akan dikirimkan ke server. Terdapat total 9 method yang dapat dikirimkan, tetapi yang paling umum digunakan adalah GET, POST, PUT, dan DELETE. Ingat bahwa server juga harus dapat mengerti method yang dikirimkan oleh klien. Nama method juga harus dituliskan dalam huruf kapital.
  • Parameter kedua dari xhr.open berisi alamat URL server yang dapat menerima dan mengerti perintah yang kita kirimkan. Untuk menjaga keamanan, kita tidak dapat mengirimkan perintah ke domain yang berbeda (misal: dari example.com ke contoh.com). Hal ini dibuat untuk menghindari pencurian data pengguna ketika perantas berhasil menanamkan kode Javascript mereka ke dalam halaman web kita. Jika memang perlu mengirimkan perintah ke domain lain, baca HTTP Access Control (CORS)
  • Parameter ketiga dari xhr.open menentukan apakah perintah yang dikirimkan bersifat asinkron atau tidak. Parameter ini bersifat opsional, dan jika tidak diisi akan bernilai true. Dalam kebanyakan kasus, parameter ini tidak perlu diisikan.

Setelah selesai melakukan inisialisasi melalui xhr.open, kita kemudian dapat mengirimkan perintah ke server dengan menggunakan method xhr.send. Method xhr.send menerima satu parameter yang bersifat opsional. Parameter ini berisi data yang akan kita kirimkan ke server. Data yang dikirimkan dapat disimpan dalam beberapa jenis objek, yaitu FormData, Blob, ArrayBufferView, Document, dan DOMString. Jika tidak mengirimkan data ke server, kita dapat mengosongkan parameter ini, atau mengisikannya dengan nilai null.

Untuk dapat mengirimkan data ke server, tentunya kita juga harus mengetahui format pengiriman data yang dikenal oleh server pada HTML. Misalnya, untuk method GET pada HTML, data dikirimkan secara otomatis melalui Query String dalam format seperti berikut:

1
http://example.com/path?param1=value1&param2=value2...

Karena bentuk format data yang sederhana ini kita dapat langsung mengirimkan data melalui URL pada server, pada method xhr.open seperti berikut:

1
2
xhr.open("GET", "http://example.com/path?param1=value1&param2=value2", true);
xhr.send(null);

Sayangnya, hal ini tidak dapat kita gunakan pada pengiriman data menggunakan method POST. Jika ingin mengirimkan data menggunakan method POST, kita harus terlebih dahulu menyimpan data yang ada di dalam objek yang dapat diterima oleh xhr.send dan mengirimkannya melalui xhr.send. Berikut adalah contoh penggunaan objek FormData untuk mengambil data dalam form dan mengirimkannya melalui POST:

1
2
3
4
5
var form     = document.querySelector("#form-login");
var formData = new FormData(form);

xhr.open("POST", "http://example.com/login");
xhr.send(formData);

Kita bahkan dapat menambahkan data baru ke FormData jika diperlukan (misalnya untuk data yang tidak perlu diisikan oleh pengguna seperti nomor pendaftaran). Kita dapat menggunakan method FormData.append untuk ini:

1
2
3
4
5
6
7
var form     = document.querySelector("#form-daftar");
var formData = new FormData(form);

formData.append("NomorPendaftaran", noDaftar++);

xhr.open("PSOT", "http://example.com/register");
xhr.send(formData);

Seperti yang dapat dilihat, FormData.append menerima dua buah parameter: parameter pertama berisikan nama data yang dikirimkan, dan parameter kedua berisi nilai (isi) dari datanya.

Menangani Respon Server

Setelah dapat mengirimkan data dan perintah ke server, langkah selanjutnya dari pemrograman AJAX adalah menerima (dan menangani) respon dari server akan perintah kita. Untuk dapat melakukan hal ini, kita harus membuat sebuah fungsi baru dan mengikatkannya pada xhr.onreadystatechange, seperti berikut:

1
2
3
4
5
var fungsiRespon = function () {
    // kode...
};

xhr.onreadystatechange = fungsiRespon;

Method xhr.onreadystatechange merupakan method yang dijalankan ketika atribut xhr.readyState dari objek XMLHttpRequest berubah nilainya. Atribut xhr.readyState menyimpan penanda status dari request yang kita kirimkan ke server. Terdapat lima nilai xhr.readyState yang dimungkinkan, yaitu:

Nilai State Deskripsi
0 UNSENT xhr.open belum dipanggil.
1 OPENED xhr.open telah dipanggil, tetapi xhr.send belum.
2 HEADERS_RECEIVED xhr.send telah dipanggil, dan server telah mengembalikan header dan status HTTP.
3 LOADING Sedang mengambil data respon dari server.
4 DONE Seluruh operasi telah selesai.

Karena kita ingin mengambil respon dari server, maka di dalam fungsiRespon kita perlu melakukan cek status dari xhr.readyState dan kemudian melakukan sesuatu jika respon server sudah didapatkna (operasi sudah selesai). Status dapat kita akses langsung seperti berikut:

1
2
3
4
5
var fungsiRespon = function () {
    if (xhr.readystate === 4) {
        // respon dari server sudah diterima
    }
}

Setelah memastikan server memberikan respon sepenuhnya, kita lalu masih harus memastikan server tidak mengembalikan pesan kesalahan. Status keberhasilan atau kesalahan pada server HTTP dikomunikasikan kepada client melalui HTTP Status Code. Contohnya, jika server sukses menjalankan perintah tanpa masalah kita akan diberi kode 200. Jika halaman tidak ditemukan maka kita akan diberikan status code 404. Dengan pengetahuan ini, kita dapat melakukan pengecekan tambahan, untuk memastikan server menjalankan perintah dengan benar. HTTP Status Code dapat diakses melalui xhr.status:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
var fungsiRespon = function () {
    if (xhr.readystate === 4) {
        if (xhr.status === 200) {
            // proses data
        } else if (xhr.status === 404) {
            alert("Lokasi URL tidak ditemukan pada server!");
        } else if (xhr.status === 500) {
            alert("Server error!");
        }
    }
}

Sampai titik ini kita sudah memastikan server mengembalikan data yang lengkap, tanpa pesan kesalahan. Selanjutnya kita dapat langsung mengakses data yang diberikan oleh server, untuk diolah lebih lanjut. Data yang diberikan oleh server dapat diakses melalui dua buah properti khusus:

  • xhr.responseText - mengambil respon server dalam format String
  • xhr.responseXML - mengambil respon server dalam objek XMLDocument

Setelah mendapatkan data dalam format sesuai kebutuhan kita, kemudian kita dapat mengolah data tersebut sesuai keinginan. Jika data kembalian yang diberikan dibuat dalam format JSON, kita harus terlebih dahulu mengakses data melalui xhr.responseText. Pembahasan lebih lanjut mengenai hal ini akan dilakukan pada bagian berikutnya.

Note

Cara pengambilan respon yang dibahas pada bagian ini adalah cara pengambilan respon untuk perintah asinkronus. Ketika menggunakan perintah sinkronus, kita cukup memasukkan kode pengolahan data setelah xhr.send karena kode akan berhenti dieksekusi sampai xhr.send selesai dijalankan.

Pengolahan Data JSON

Seperti yang telah dijelaskan pada awal tulisan, meskipun AJAX memiliki kata XML di dalamnya, pada prakteknya kebanyakan pertukaran informasi dan data pada aplikasi web modern dilakukan melalui JSON. JSON merupakan format native dari Javascript, di mana format penulisan JSON sama persis dengan format penulisan objek pada Javacsript (yang bahkan nampak dari namanya: JavaScript Object Notation).

Untuk bekerja dengan JSON dalam Javascript, kita dapat menggunakan objek JSON yang hanya memiliki dua method: JSON.parse dan JSON.stringify. JSON.parse mengambil sebuah string JSON dan menjadikannya objek Javascript, sementara JSON.stringify melakukan hal sebaliknya: mengubah objek Javascript menjadi string JSON yang valid. Untuk dapat lebih mudah memahami kegunaan dari kedua method ini, kita akan langsung melihat contoh penggunaannya.

Membaca JSON Menjadi Objek

JSON.parse menerima dua buah parameter, dengan parameter pertama berupa string yang akan diubah menjadi objek dan parameter kedua yang bersifat opsional:

1
2
3
4
5
var response = "{\"health\": 3000, \"mana\": 400, \"str\": 86, \"agi\": 63, \"int\": 66}";
var ResObj   = JSON.parse(response);

ResObj["health"]; // 3000
ResObj.mana;      // 400

Parameter kedua dari JSON.parse dapat kita gunakan untuk melakukan sesuatu terhadap data pada string, sebelum data tersebut dimasukkan ke dalam objek. Parameter kedua ini menerima sebuah fungsi dengan dua parameter yang masing-masing adalah nama atribut dan nilai atribut dari string JSON yang sedang dibaca. Fungsi akan dijalankan terhadap semua atribut JSON yang ada, sehingga kita dapat mengubah nilai dari atribut jika diinginkan. Nama umum dari parameter kedua ini adalah reviver. Perhatikan kode berikut:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
var reviver = function (k, v) {
    console.log(k + ": " + v);
};

var data = '{"satu": 1, "dua": 2, "tiga": {"empat": 4, "lima": 5}}';

JSON.parse(data, reviver);
// Keluaran:
// satu: 1
// dua: 2
// empat: 4
// lima: 5
// tiga: [object Object]
// : [object Object]

Beberapa hal yang dapat kita pelajari dari kode di atas:

  • Fungsi revivier dijalankan ke masing-masing atribut JSON secara berurutan (“satu”, “dua”, “tiga”).
  • Ketika menemukan atribut yang memiliki nilai objek (JSON) lain, reviver terlebih dahulu diterapkan pada atribut objek yang di dalam (pada contoh kita: “empat” dan “lima” tercetak terlebih dahulu sebelum “tiga”).
  • Terdapat satu atribut tambahan yang tidak ada dalam data, yaitu cetakan terakhir (: [object: Object]). Atribut ini mewakili keseluruhan JSON yang kita kirimkan, dan akan selalu dibaca paling terkhir. Hal ini dibuat agar kita juga dapat mengubah objek utama (misal: menambahkan method) jika diperlukan. Kita tetap harus ingat untuk menangani kasus ini bahkan ketika kita tidak mengubah objek utama, biasanya dengan mengembalikan nilai awal (v pada kode di atas) agar JSON.parse tidak mengembalikan undefined.

Untuk memperjelas masalah penanganan objek utama pada poin ketiga, perhatikan kode berikut:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
var kosong = JSON.parse(data, function (k, v) {
    return v * 2;
});

var isi = JSON.parse(data, function (k, v) {
    // if (k === "") return v;
    if (k === "" || typeof v === "object") return v;

    return v * 2;
});

kosong; // NaN
isi;    // {"satu": 2, "dua": 4, "tiga": {"empat": 8, "lima": 10}}

Pada kode di atas, kita dapat melihat bagaimana jika kita tidak melakukan pengecekan nilai k kosong maka objek hasil tidak akan dikembalikan. Sebagai latihan, coba ganti baris if pada fungsi milik isi dengan yang dikomentari dan lihat hasilnya. Kegunaan dari cek typeof v === "object diberikan sebagai latihan kepada pembaca.

Memanfaatkan pengetahuan ini, kita dapat mengembangkan fungsi reviver yang membuat objek penuh beserta dengan method baru seperti berikut:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
var response = "{\"health\": 3000, \"mana\": 400, \"str\": 86, \"agi\": 63, \"int\": 66}";
var reviver = function (k, v) {
    if (k === "") {
        v.getStr = function () {
            return v.str;
        }

        return v;
    }

    return v * 2;
};

var TransformedObj = JSON.parse(response, reviver);

TransformedObj["health"]; // 6000
TransformedObj.mana;      // 800
TransformedObj.getStr();  // 172

Selanjutnya, mari kita lihat bagaimana cara mengubah objek menjadi string JSON.

Mengubah Objek Menjadi String

Selain menerima string JSON dan mengubahnya ke dalam objek Javascript, seringkali kita juga perlu mengirimkan data baru ke server, yang berasal dari objek Javascript. Untuk kasus ini kita memerlukan mekanisme untuk mengubah objek menjadi string JSON. Javascript menyediakan method JSON.stringify untuk melakukan hal ini. Penggunaan sederhana method ini sangat mudah:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
var obj = {
    model: "L925",
    size: 3.5,
    age: 18,
    conn: "4G"
};

var jsonString = JSON.stringify(obj);

jsonString; // '{"model":"L925","size":3.5,"age":18,"conn":"4G"}'

Begitupun, JSON.stringify memiliki parameter kedua dan ketiga yang sifatnya opsional namun cukup berguna. Parameter kedua dari JSON.stringify mirip dengan parameter kedua dari JSON.parse, yaitu sebuah fungsi yang digunakan untuk melakukan proses data dalam objek sebelum objek tersebut dijadikan string. Berikut adalah contoh penggunaannya:

1
2
3
4
5
6
var filteredJSON = JSON.stringify(obj, function (k, v) {
    if (typeof v === "string") return undefined;
    return v;
});

filteredJSON; // '{"size":3.5,"age":18}'

Seperti yang dilihat di atas, fungsi yang dikirimkan diterapkan ke semua atribut objek untuk kemudian diproses. Kita juga dapat mengisikan array pada parameter kedua. Jika diisikan dengan array, isi dari array akan dianggap menjadi atribut yang ingin kita masukkan dalam string JSON, seperti berikut:

1
2
3
var altJSON = JSON.stringify(obj, ["model", "conn"]);

altJSON; // '{"model":"L925","conn":"4G"}'

Parameter ketiga dari JSON.stringify digunakan untuk memperindah string JSON hasil proses. Kita dapat mengirimkan string yang dijadikan sebagai spasi pemisah pada string JSON yang dihasilkan. Jika parameter ketiga diisikan angka, maka angka tersebut akan menjadi jumlah spasi yang dimasukkan pada pemisah string JSON. Langsung saja, berikut contoh penggunaannya:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
JSON.stringfiy(obj, ["model", "conn"], "\t");
// keluaran:
// "{
//    "model": "L925",
//    "conn": "4G"
// }"

JSON.stringfiy(obj, ["model", "conn"], "aaaa");
// keluaran:
// "{
// aaaa"model": "L925",
// aaaa"conn": "4G"
// }"

JSON.stringfiy(obj, ["model", "conn"], 4);
// keluaran:
// "{
//     "model": "L925",
//     "conn": "4G"
// }"
comments powered by Disqus
Kembali ke bertzzie.com