news

Jumat, 12 Juni 2020

Belajar Menggunakan Ajax Menggunakan XMLHttpRequest


Persiapan Proyek Latihan

Sebelum melanjutkan ke materi selanjutnya, dalam pembelajaran kali ini Anda akan membangun aplikasi web sederhana yang berfungsi untuk menampilkan, menambah, mengubah daftar buku.
2020031323085174e5859671d6a570d425ec2cd2067bdf.gif
Untuk itu mari kita persiapkan terlebih dahulu project starter-nya. Silakan unduh proyek awalnya pada tautan berikut: DicodingBooks. download
Setelah mengunduhnya, silakan ekstrak folder tersebut pada lokasi yang Anda inginkan. Di sini kita mencontohkan pada C -> Users -> Dicoding -> Desktop .
20200313230922c6e2ae6e7051445cef3959ae5fa83220.png
Setelah berhasil Anda ekstrak, maka pada lokasi yang ditentukan akan terdapat folder dengan nama “DicodingBooks”.
20200313230959a9dc006c2aa1e3ef48596b3b4d85e3b2.png
Buka folder proyek tersebut menggunakan code editor Anda. Lalu pada terminal (yang dibuka pada folder proyek) tuliskan perintah:

  1. npm install


Perintah tersebut berfungsi untuk memasang seluruh package yang terdapat di devDependencies dan dependencies pada berkas package.json. Setelah proses memasang package telah selesai, akan terbentuk folder node_modules pada proyek Dicoding Books.
20200313231044fe4854e09b0bc57806d2a415b06d5d00.png
Seperti yang sudah kita pelajari pada modul sebelumnya, proyek ini menggunakan webpack dengan konfigurasi sama seperti yang sudah kita pelajari. Untuk menjalankan proyek pada local server, kita tuliskan perintah berikut pada terminal.

  1. npm run start-dev


Buka browser dan arahkan ke alamat localhost:8080. Maka proyek Dicoding Books akan tampil pada browser.
202003132311222bed90bf92592d75d973c5b0067783ab.png
Ini merupakan proyek awal sehingga ia belum berfungsi sebagaimana dicontohkan pada gambar gif sebelumnya. 
Jika kita lihat pada source code yang ada di dalam proyek tersebut, tepatnya pada berkas src -> script -> main.js. Di sana kita bisa melihat fungsi kosong.
  1. function main() {
  2.  
  3.     const getBook = () => {
  4.         // tuliskan kode di sini!
  5.     };
  6.  
  7.  
  8.     const insertBook = (book) => {
  9.         // tuliskan kode di sini!
  10.     };
  11.  
  12.     const updateBook = (book) => {
  13.         // tuliskan kode di sini!
  14.     };
  15.  
  16.     const removeBook = (bookId) => {
  17.         // tuliskan kode di sini!
  18.     };
  19.  
  20. ........
  21. }
  22.  
  23. export default main;

Nah tugas kita nanti adalah melengkapi fungsi yang tersebut hingga proyek Dicoding Book dapat berfungsi seperti yang diharapkan.
Kita juga bisa lihat kode lainnya pada main.js, seperti kode ini:
  1. /*
  2.         jangan ubah kode di bawah ini ya!
  3. */
  4.  
  5.     const renderAllBooks = (books) => {
  6.         const listBookElement = document.querySelector("#listBook");
  7.         listBookElement.innerHTML = "";
  8.  
  9.         books.forEach(book => {
  10.             listBookElement.innerHTML += `
  11.                 <div class="col-lg-4 col-md-6 col-sm-12" style="margin-top: 12px;">
  12.                     <div class="card">
  13.                         <div class="card-body">
  14.                             <h5>(${book.id}) ${book.title}</h5>
  15.                             <p>${book.author}</p>
  16.                             <button type="button" class="btn btn-danger button-delete" id="${book.id}">Hapus</button>
  17.                         </div>
  18.                     </div>
  19.                 </div>
  20.             `;
  21.         });
  22.  
  23.         const buttons = document.querySelectorAll(".button-delete");
  24.         buttons.forEach(button => {
  25.             button.addEventListener("click", event => {
  26.                 const bookId = event.target.id;
  27.                 removeBook(bookId);
  28.             })
  29.         })
  30.     };
  31.  
  32.     const showErrorAlert = (message = "Check your internet connection") => {
  33.         alert(message);
  34.     };
  35.  
  36.     document.addEventListener("DOMContentLoaded", () => {
  37.  
  38.         const inputBookId = document.querySelector("#inputBookId");
  39.         const inputBookTitle = document.querySelector("#inputBookTitle");
  40.         const inputBookAuthor = document.querySelector("#inputBookAuthor");
  41.         const buttonSave = document.querySelector("#buttonSave");
  42.         const buttonUpdate = document.querySelector("#buttonUpdate");
  43.  
  44.         buttonSave.addEventListener("click", function () {
  45.             const book = {
  46.                 id: Number.parseInt(inputBookId.value),
  47.                 title: inputBookTitle.value,
  48.                 author: inputBookAuthor.value
  49.             };
  50.             insertBook(book)
  51.         });
  52.  
  53.         buttonUpdate.addEventListener("click", function () {
  54.             const book = {
  55.                 id: Number.parseInt(inputBookId.value),
  56.                 title: inputBookTitle.value,
  57.                 author: inputBookAuthor.value
  58.             };
  59.  
  60.             updateBook(book)
  61.         });
  62.         getBook();
  63.     });
  64. }
  65.  
  66. export default main;

Fungsi-fungsi di atas merupakan fungsi yang membantu kita dalam memanipulasi DOM. Fungsi renderAllBooks digunakan untuk merender atau menampilkan data books yang didapat ke dalam DOM. Fungsi showErrorAlert digunakan untuk menampilkan window.alert() dengan pesan yang diambil dari argument fungsinya.
Kemudian fungsi di dalam event DOMContentLoaded, di sana terdapat kode untuk mengakses elemen <input> dan <button> yang ditampilkan pada halaman agar elemen tersebut dapat berfungsi dengan semestinya, termasuk dalam membuat objek book yang dikirimkan pada parameter fungsi updateBook dan insertBook.
Lalu terdapat juga kode lain yang dituliskan pada src -> index.js.
  1. /*
  2.         jangan ubah kode di bawah ini ya!
  3. */
  4.  
  5. import "regenerator-runtime";
  6. import "bootstrap/dist/css/bootstrap.min.css";
  7. import "./styles/main.css";
  8. import main from "./scripts/main";
  9.  
  10. main();

Berkas ini merupakan endpoint dari proyek Dicoding Books. Kode yang dituliskan pada berkas ini tidak banyak, hanya sebatas melakukan impor dari modul atau package yang dibutuhkan dalam menjalankan aplikasinya.
Anda bisa mengetahui bagaimana proyek ini bekerja dengan mempelajari seluruh kode yang ada. Namun khusus kode di atas, jangan Anda ubah ya.

AJAX using XHR

XMLHttpRequest atau XHR merupakan objek yang tersedia pada browser yang digunakan untuk membuat HTTP Requests menggunakan JavaScript. Karena namanya kita mungkin beranggapan bahwa XHR hanya mendukung format data XML, tetapi nyatanya saat ini XHR dapat digunakan oleh banyak format, bukan hanya XML.
Walaupun sekarang terdapat cara yang lebih modern yaitu menggunakan fetch, namun masih ada kok beberapa developer yang menggunakan XHR dalam melakukan HTTP Request. Alasannya karena alasan dukungan browser tua atau suatu fitur yang tidak bisa fetch lakukan seperti tracking upload progress.

Basic Usage

XMLHttpRequest dapat berjalan secara synchronous maupun asynchronous. Namun kebanyakan kasus HTTP Request sebaiknya asynchronous.
Contoh penggunaan dasar dari XMLHttpRequest adalah seperti ini:
202003132318522fefb326486e99f9449b3ea0b5d8cb31.png
Langkah awal untuk menggunakan XMLHttpRequest adalah dengan membuat instance baru dari objek XMLHttpRequest seperti ini:

  1. const xhr = new XMLHttpRequest();


Lalu pada instance dari objek tersebut (xhr) kita tentukan callback function ketika request berhasil (onload) dan ketika request gagal (onerror).

  1. xhr.onload = function () {

  2. console.log(this.responseText);

  3. }

  4. xhr.onerror = function () {

  5. console.log("Ups something error")

  6. }


Di dalam callback function tersebut, nilai dari this merupakan XHR objek. Sehingga this.responseText akan memiliki nilai response (dalam bentuk text) dari server. Ingat karena pada callback function tersebut nilai this merupakan XHR objek, kita tidak dapat menggunakan gaya arrow function dalam menuliskan callback function-nya.

  1. xhr.onload = () => {

  2.     // akan menyebabkan error, karena arrow function tidak memiliki this.

  3.     console.log(this.responseText);

  4. }


Selanjutnya kita tentukan HTTP Method dan URL yang dituju dengan menggunakan method .open()

  1. xhr.open("GET", "https://api-to-call.com/endpoint");


Nah, langkah akhir adalah mengirimkan request yang sudah kita konfigurasi di atas menggunakan method .send().

  1. xhr.send();


Sehingga seluruh kode dalam penggunaan dasar dari XMLHttpRequest dengan contoh target url berikut https://web-server-book-dicoding.appspot.com/list adalah seperti ini:

  1. const xhr = new XMLHttpRequest();

  2.  

  3. xhr.onload = function () {

  4.  console.log(this.responseText)

  5. }

  6. xhr.onerror = function () {

  7.  console.log("Ups something error")

  8. }

  9.  

  10. xhr.open("GET", "https://web-server-book-dicoding.appspot.com/list");

  11. xhr.send();


Coba Anda copy dan paste kode di atas dan jalankan pada console devTools. Jika request berhasil, Anda akan mendapatkan data dalam bentuk JSON String. Data tersebut bisa Anda olah menjadi JavaScript objek dengan mengubahnya menggunakan method JSON.parse().

  1. JSON.parse(this.responseText)


Anda juga bisa mencoba menjalankan potongan kode di atas pada repl.it melalui tautan berikut:
https://repl.it/@dicodingacademy/163-06-AJAX-XHR-basic?lite=true

Header and Body Request using XHR

Sebelumnya kita sudah belajar bagaimana cara menggunakan dasar XMLHttpRequest dalam membuat sebuah GET Request. Lalu bagaimana jika kita ingin menggunakan method POST dan menetapkan properti pada Header ? Lalu bagaimana cara mengirimkan data pada body HTTP Request? Yuk kita bahas permasalahan tersebut satu per satu.

Set Header Property

Dalam menggunakan Web API tidak selamanya kita hanya menggunakan GET request saja, terutama ketika request yang kita inginkan bertujuan mengubah atau menambahkan data. Web API biasanya meminta kita untuk melakukannya dengan method POST atau PUT
Tak jarang juga Web API meminta kita untuk menetapkan properti tertentu pada request header untuk menunjukkan credential yang kita miliki. Request tersebut sudah pernah kita coba ya menggunakan Postman. Tapi bagaimana ya caranya jika menggunakan XHR?
Untuk menetapkan properti pada request header, Anda dapat gunakan method setRequestHeader() pada instance XMLHttpRequest setelah menetapkan method .open()
Method tersebut menerima dua parameter. Parameter pertama merupakan nama properti dan parameter yang kedua adalah nilai yang akan ditetapkan pada properti tersebut. Sehingga untuk menetapkan properti Content-Type dengan nilai application/json pada request kita dapat melakukannya dengan cara:
  1. const xhr = new XMLHttpRequest();
  2.  
  3. xhr.onload = function() {
  4.  console.log(this.responseText);
  5. }
  6.  
  7. xhr.onerror = function() {
  8.  console.log("Ups something error");
  9. }
  10.  
  11. xhr.open("POST", "https://web-server-book-dicoding.appspot.com/add");
  12.  
  13. // menambahkan properti pada header request
  14. xhr.setRequestHeader("Content-Type", "application/json");

Kita dapat menetapkan properti pada request header sebanyak yang kita perlukan
  1. const xhr = new XMLHttpRequest();
  2.  
  3. xhr.onload = function() {
  4.  console.log(this.responseText);
  5. }
  6.  
  7. xhr.onerror = function() {
  8.  console.log("Ups something error");
  9. }
  10.  
  11. xhr.open("POST", "https://web-server-book-dicoding.appspot.com/add");
  12.  
  13. // menambahkan properti pada header request
  14. xhr.setRequestHeader("Content-Type", "application/json");
  15. xhr.setRequestHeader("X-Auth-Token", "12345")

Cukup mudah bukan?

Set Data to Body Request

Lalu untuk menetapkan data pada body request, lakukanlah pada method .send() dari instance XMLHttpRequest. Contohnya untuk mengirimkan data JSON String pada body request, begini caranya: 
  1. const xhr = new XMLHttpRequest();
  2.  
  3. xhr.onload = function() {
  4.  console.log(this.responseText);
  5. }
  6.  
  7. xhr.onerror = function() {
  8.  console.log("Ups something error");
  9. }
  10.  
  11. xhr.open("POST", "https://web-server-book-dicoding.appspot.com/add");
  12.  
  13. // menambahkan properti pada header request
  14. xhr.setRequestHeader("Content-Type", "application/json");
  15. xhr.setRequestHeader("X-Auth-Token", "12345")
  16.  
  17. const book = {
  18.  id: 10,
  19.  title: "Edensor",
  20.  author: "Andrea Hirata"
  21. }
  22.  
  23. xhr.send(JSON.stringify(book));

Sebenarnya tidak hanya JSON format yang dapat dikirimkan melalui body, pada situs MDN menyebutkan bahwa kita dapat mengirimkan dokumen yang sudah ter-serialized sebelum dikirim, atau data lain yang terdaftar pada Fetch spec seperti BlobBufferSourceFormDataURLSeachParamReadableStream atau USVString object.
Contoh kode di atas dapat Anda temukan pada tautan berikut https://repl.it/@dicodingacademy/163-06-AJAX-XHR-Header-and-Body?lite=true. Anda bisa coba lakukan POST Request dengan menjalankan potongan kode tersebut

Latihan AJAX menggunakan XHR pada Dicoding Books

Sebelumnya kita sudah mengetahui teori dari penggunaan XHR dalam membuat HTTP Request. Nah, kali ini kita akan mencoba melengkapi fungsi dalam menampilkan, menambahkan, mengubah dan menghapus data buku melalui Dummy Books API menggunakan AJAX dengan XHR.
Untuk itu pastikan Anda sudah membaca dokumentasi penggunaan API tersebut pada url berikut: https://web-server-book-dicoding.appspot.com/
Langkah pertama silakan buka proyek DicodingBooks yang telah Anda siapkan dengan text editor yang Anda gunakan.
202003132329421a8695df5dbf0702477d2ee198d708e4.png
Pastikan juga Anda sudah menjalankan perintah npm install pada terminal di dalam root folder proyek. Perintah tersebut berfunfsi untuk memasang seluruh dependencies dan devDependencies yang dibutuhkan oleh proyek DicodingBooks. Kemudian tuliskan perintah npm run start-dev pada terminal untuk menjalankan aplikasi pada default browser yang Anda gunakan.
20200313233101d662cb44f697c245b056713dc7ce8ad1.png
Setelah aplikasi tampak pada browser, kita bisa memulai menuliskan kode pada berkas src -> scripts -> main.js. Pada latihan AJAX kita akan hanya menuliskan kode pada berkas tersebut, jadi pastikan Anda tidak mengubah kode di berkas lain atau kode yang sudah diberi tanda ini.

  1. /*

  2.         jangan ubah kode di bawah ini ya!

  3. */


Setelah semuanya siap, mari mulai tuliskan kode dalam membuat AJAX dengan XHR pada fungsi getBook() terlebih dahulu

Melengkapi Fungsi getBook

Fungsi getBook() merupakan fungsi yang digunakan untuk mendapatkan daftar buku yang ada pada Web API. Dokumentasi Web API menyebutkan bahwa untuk mendapatkan daftar buku, kita gunakan:
  • Endpoint (URL): /list
  • method: GET
Dari informasi tersebut pada fungsi getBook kita dapat membuat GET request dengan menuliskan kode seperti ini:
  1. const getBook = () => {
  2.     // membuat instance dari XMLHttpRequest
  3.     const xhr = new XMLHttpRequest();
  4.         
  5.     //menetapkan callback jika response sukses dan error
  6.     xhr.onload = function() {
  7.         const responseJson = JSON.parse(this.responseText);
  8.         if(responseJson.error) {
  9.            showResponseMessage(responseJson.message);
  10.         } else {
  11.            renderAllBooks(responseJson.books);
  12.         }
  13.     }
  14.  
  15.     xhr.onerror = function() {
  16.         showResponseMessage();
  17.     }
  18.  
  19.      // Membuat GET request dan menetapkan target URL
  20.      xhr.open("GET", "https://web-server-book-dicoding.appspot.com/list");
  21.      // Mengirimkan request
  22.      xhr.send();
  23. };

Respon pada request di atas akan menghasilkan JSON dengan struktur seperti ini:
  1. {
  2.   "error": false,
  3.   "message": "success",
  4.   "books": [
  5.     {
  6.       "id": 1,
  7.       "title": "Laskar Pelangi",
  8.       "author": "Andrea Hirata"
  9.     },
  10.     {
  11.       "id": 2,
  12.       "title": "Filosofi Kopi",
  13.       "author": "Dewi Lestari"
  14.     },
  15.     {
  16.       "id": 3,
  17.       "title": "Clean Code",
  18.       "author": "Robert C Martin"
  19.     },
  20.     {
  21.       "id": 4,
  22.       "title": "Harry Potter and the Philosopher's Stone",
  23.       "author": "J.K. Rowling"
  24.     },
  25.     {
  26.       "id": 5,
  27.       "title": "Sang Pemimpi",
  28.       "author": "Andrea Hirata"
  29.     },
  30.     {
  31.       "id": 6,
  32.       "title": "Eloquent JavaScript: A Modern Introduction to Programming",
  33.       "author": "Marijn Haverbeke"
  34.     }
  35.   ]
  36. }

Kita dapat memanfaatkan properti eror untuk memeriksa apakah response tersebut bersifat eror atau tidak. Sehingga kita dapat memanfaatkannya untuk mengontrol alur kode yang berjalan.
  1. const responseJson = JSON.parse(this.responseText);
  2. if(responseJson.error) {
  3.     showResponseMessage(responseJson.message);
  4. } else {
  5.     renderAllBooks(responseJson.books);
  6. }

Coba simpan perubahan kode di atas dan lihat pada browser. Seharusnya aplikasi sudah bisa menampilkan data yang didapatkan dari Web API.
20200313233429c5539331938498dec71e57b54700cd94.png

Melengkapi Fungsi insertBook

Setelah kita berhasil melengkapi kode pada fungsi getBook, selanjutnya giliran fungsi insertBook yang akan kita lengkapi kodenya. Fungsi ini digunakan untuk menambahkan data buku melalui Web API. Dokumentasi menyebutkan bahwa untuk menambahkan data buku kita perlu membuat request dengan ketentuan berikut:
  • endpoint : /add
  • method: POST
  • Header:
  • Content-Type: application/json
  • X-Auth-Token: 12345
  • Body:  {"id" : number, "title" : string, "author" : string }
Dari informasi di atas, kita dapat membuat POST request menggunakan XHR dengan kode seperti ini:
  1. const insertBook = (book) => {
  2. // Membuat instance dari XMLHttpRequest
  3. const xhr = new XMLHttpRequest();
  4.  
  5. //menetapkan callback jika response sukses dan error
  6. xhr.onload = function() {
  7. const responseJson = JSON.parse(this.responseText);
  8. showResponseMessage(responseJson.message);
  9. getBook();
  10. }
  11.  
  12. xhr.onerror = function() {
  13. showResponseMessage();
  14. }
  15.  
  16. // Membuat POST request dan menetapkan target URL
  17. xhr.open("POST", "https://web-server-book-dicoding.appspot.com/add");
  18. // Mementapkan properti Content-Type dan X-Auth-Token pada Header request
  19. xhr.setRequestHeader("Content-Type", "application/json");
  20. xhr.setRequestHeader("X-Auth-Token", "12345");
  21.  
  22. // Mengirimkan request dan menyisipkan JSON.stringify(book) pada body
  23. xhr.send(JSON.stringify(book));
  24. };

Perhatikan kode pada penetapan callback xhr.onload berikut ini:
  1. xhr.onload = function() {
  2.        const responseJson = JSON.parse(this.responseText);
  3.        showResponseMessage(responseJson.message);
  4.        getBook();
  5. }
Pada akhir kodenya, kita memanggil fungsi getBook(). Fungsi tersebut perlu kita panggil agar ketika buku berhasil dimasukkan, daftar buku yang ditampilkan pada aplikasi akan ikut diperbarui, sehingga data baru akan tampil walaupun ia baru saja  dimasukkan. Dengan catatan, browser tidak melakukan reload ya ketika menampilkan data yang baru. Keren kan? Nah inilah keistimewaan ketika menggunakan teknik AJAX, karena kita dapat memperbarui data yang diambil dari server dengan cepat.
Silakan simpan perubahan kode yang sudah kita terapkan, kemudian coba kembali aplikasi pada browser. Seharusnya aplikasi sudah dapat menambahkan data buku baru.
202003132338395ae1b7c0e093de97637b9040bc83eac9.gif
Oiya, kita juga dapat menyederhanakan penulisan target URL dengan memisahkan nilai base url dan endpoint.
20200313233910df29323c053851ade26157c7aaa27a88.png
Karena pada setiap fungsi request yang sudah kita buat maupun yang akan kita nantinya, Base URL akan menggunakan nilai yang sama. Sehingga baiknya ia dibuatkan variabel tersendiri dan pada tiap fungsi request kita hanya menetapkan endpoint-nya saja.
  1. function main() {
  2.  
  3.    const baseUrl = "https://web-server-book-dicoding.appspot.com";
  4.  
  5.    const getBook = () => {
  6. .......
  7.        xhr.open("GET", `${baseUrl}/list`);
  8. .......
  9. };
  10.  
  11.    const insertBook = (book) => {
  12. .......
  13.  
  14.        // Membuat GET request dan menetapkan target URL (endpoint)
  15.        xhr.open("POST", `${baseUrl}/add`);
  16. ........
  17. };
  18.  
  19. .......

Melengkapi Fungsi updateBook

Fungsi selanjutnya yang harus kita lengkapi adalah fungsi updateBook. Fungsi ini digunakan untuk mengubah data buku yang ada, baik itu mengubah title atau author dari buku melalui Web API. Dokumentasi menyebutkan bahwa untuk mengubah data buku kita perlu membuat request dengan ketentuan berikut:
  • endpoint : /edit/:id
  • method: PUT
  • Header:
  • Content-Type: application/json
  • X-Auth-Token: 12345
  • Body:  {"id" : number, "title" : string, "author" : string }
Dari informasi yang didapatkan di atas, kita dapat membuat PUT request menggunakan XHR dengan kode seperti ini:
  1. const updateBook = (book) => {
  2.     // Membuat instance dari XMLHttpRequest
  3.     const xhr = new XMLHttpRequest();
  4.  
  5.     //menetapkan callback jika response sukses dan error
  6.     xhr.onload = function() {
  7.        const responseJson = JSON.parse(this.responseText);
  8.        showResponseMessage(responseJson.message);
  9.        getBook();
  10.     }
  11.  
  12.     xhr.onerror = function() {
  13.        showResponseMessage();
  14.     }
  15.  
  16.     // Membuat PUT request dan menetapkan target URL
  17.     xhr.open("PUT", `${baseUrl}/edit/${book.id}`);
  18.         
  19.     // Mementapkan properti Content-Type dan X-Auth-Token pada Header request
  20.     xhr.setRequestHeader("Content-Type", "application/json");
  21.     xhr.setRequestHeader("X-Auth-Token", "12345");
  22.  
  23.     // Mengirimkan request dan menyisipkan JSON.stringify(book) pada body
  24.     xhr.send(JSON.stringify(book));
  25. };

Jika dilihat pada kode di atas, kode yang dituliskan mirip seperti fungsi insertBook, hanya berbeda pada penggunaan method request dan target URL-nya.
Silakan simpan perubahan kode yang sudah kita terapkan, kemudian coba kembali aplikasi pada browser. Seharusnya aplikasi sudah dapat mengubah data buku.
20200313234232416bdf664e23e938f8e6814e852104db.gif

Melengkapi Fungsi deleteBook

Fungsi terakhir yang perlu kita lengkapi adalah deleteBook. Fungsi ini digunakan untuk menghapus data buku yang ada melalui Web API. Dokumentasi menyebutkan bahwa untuk menghapus data buku kita perlu membuat request dengan ketentuan berikut:
  • endpoint : /delete/:id
  • method: DELETE
  • Header:
  • X-Auth-Token: 12345
Dari informasi yang didapatkan di atas, kita dapat membuat DELETE request menggunakan XHR dengan kode seperti ini:
  1. const removeBook = (bookId) => {
  2.    // Membuat instance dari XMLHttpRequest
  3.    const xhr = new XMLHttpRequest();
  4.  
  5.    //menetapkan callback jika response sukses dan error
  6. xhr.onload = function() {
  7.   const responseJson = JSON.parse(this.responseText);
  8. showResponseMessage(responseJson.message);
  9. getBook();
  10. }
  11.  
  12. xhr.onerror = function() {
  13. showResponseMessage();
  14. }
  15.  
  16.    // Membuat DELETE request dan menetapkan target URL
  17.    xhr.open("DELETE", `${baseUrl}/delete/${bookId}`);
  18.  
  19.    // Mementapkan properti Content-Type dan X-Auth-Token pada Header request
  20.    xhr.setRequestHeader("X-Auth-Token", "12345");
  21.  
  22.    // Mengirimkan request
  23. xhr.send();
  24. };

Silakan simpan perubahan kode yang sudah kita terapkan, kemudian coba kembali aplikasi pada browser. Seharusnya aplikasi sudah dapat menghapus data buku yang ada.
20200313234626db5b1a21e54700fce2e7c08cd359e0ef.gif
Selamat! Dengan begitu aplikasi Dicoding Books sudah berfungsi sepenuhnya! Berikut seluruh kode pada fungsi yang sudah kita lengkapi.
  1. function main() {
  2.  
  3.     const baseUrl = "https://web-server-book-dicoding.appspot.com";
  4.  
  5.     const getBook = () => {
  6.         // membuat instance dari XMLHttpRequest
  7.         const xhr = new XMLHttpRequest();
  8.         
  9.         //menetapkan callback jika response sukses dan error
  10.         xhr.onload = function() {
  11.             const responseJson = JSON.parse(this.responseText);
  12.             if(responseJson.error) {
  13.                 showResponseMessage(responseJson.message);
  14.             } else {
  15.                 renderAllBooks(responseJson.books);
  16.             }
  17.         }
  18.  
  19.         xhr.onerror = function() {
  20.             showResponseMessage();
  21.         }
  22.  
  23.         // Membuat GET request dan menetapkan target URL
  24.         xhr.open("GET", `${baseUrl}/list`);
  25.         // Mengirimkan request
  26.         xhr.send();
  27.     };
  28.  
  29.     const insertBook = (book) => {
  30.         // Membuat instance dari XMLHttpRequest
  31.         const xhr = new XMLHttpRequest();
  32.  
  33.         //menetapkan callback jika response sukses dan error
  34.         xhr.onload = function() {
  35.            const responseJson = JSON.parse(this.responseText);
  36.            showResponseMessage(responseJson.message);
  37.            getBook();
  38.          }
  39.  
  40.         xhr.onerror = function() {
  41.             showResponseMessage();
  42.         }
  43.  
  44.         // Membuat GET request dan menetapkan target URL
  45.         xhr.open("POST", `${baseUrl}/add`);
  46.         
  47.         // Mementapkan properti Content-Type dan X-Auth-Token pada Header request
  48.         xhr.setRequestHeader("Content-Type", "application/json");
  49.         xhr.setRequestHeader("X-Auth-Token", "12345");
  50.  
  51.         // Mengirimkan request dan menyisipkan JSON.stringify(book) pada body
  52.         xhr.send(JSON.stringify(book));
  53.     };
  54.  
  55.     const updateBook = (book) => {
  56.         // Membuat instance dari XMLHttpRequest
  57.         const xhr = new XMLHttpRequest();
  58.  
  59.         //menetapkan callback jika response sukses dan error
  60.         xhr.onload = function() {
  61.            const responseJson = JSON.parse(this.responseText);
  62.            showResponseMessage(responseJson.message);
  63.            getBook();
  64.          }
  65.  
  66.         xhr.onerror = function() {
  67.             showResponseMessage();
  68.         }
  69.  
  70.         // Membuat GET request dan menetapkan target URL
  71.         xhr.open("PUT", `${baseUrl}/edit/${book.id}`);
  72.         
  73.         // Mementapkan properti Content-Type dan X-Auth-Token pada Header request
  74.         xhr.setRequestHeader("Content-Type", "application/json");
  75.         xhr.setRequestHeader("X-Auth-Token", "12345");
  76.  
  77.         // Mengirimkan request dan menyisipkan JSON.stringify(book) pada body
  78.         xhr.send(JSON.stringify(book));
  79.     };
  80.  
  81.     const removeBook = (bookId) => {
  82.         // Membuat instance dari XMLHttpRequest
  83.         const xhr = new XMLHttpRequest();
  84.  
  85.         //menetapkan callback jika response sukses dan error
  86.         xhr.onload = function() {
  87.            const responseJson = JSON.parse(this.responseText);
  88.            showResponseMessage(responseJson.message);
  89.            getBook();
  90.          }
  91.  
  92.         xhr.onerror = function() {
  93.             showResponseMessage();
  94.         }
  95.  
  96.         // Membuat DELETE request dan menetapkan target URL
  97.         xhr.open("DELETE", `${baseUrl}/delete/${bookId}`);
  98.         
  99.         // Mementapkan properti Content-Type dan X-Auth-Token pada Header request
  100.         xhr.setRequestHeader("X-Auth-Token", "12345");
  101.  
  102.         // Mengirimkan request
  103.         xhr.send();
  104.     };
  105. .........

Penerapan AJAX menggunakan XHR dalam melengkapi fungsi yang ada di proyek Dicoding Books dapat Anda temukan juga pada repository berikut: https://github.com/dicodingacademy/a163-bfwd-labs/tree/302-dicoding-books-xhr