Universitas Kebudayaan Digital Makassar

Universitas Kebudayaan Digital Makassar (UKDMKS) memadukan inovasi teknologi digital dengan pelestarian budaya lokal. Bergabunglah untuk membangun masa depan berbasis budaya dan teknologi!

javascript

Belajar Menggunakan Ajax Menggunakan Fetch Bagian Pertama

Setelah kita belajar bagaimana membuat http request menggunakan XMLHttpRequest, mungkin sebagian dari kita berpikir, “Adakah cara yang lebih mudah dalam membuat http request tanpa harus melalui banyak langkah?”. 
Nah jawabannya ada! Yaitu dengan menggunakan Fetch!

Fetch merupakan cara baru dalam membuat network request. Dengan fetch kita dapat membuat http request lebih mudah tanpa harus membuat instance dan memanggil banyak method. 
Satu hal lagi yang membuat fetch jauh lebih baik adalah fetch memanfaatkan Promise sehingga kita dapat mengurangi penerapan callback, dan dapat dituliskan dengan gaya synchronous menggunakan async dan await.

Fetch Basic Usage

Seperti yang sudah kita ketahui, fetch memanfaatkan promise dalam melakukan tugasnya, sehingga network request yang dibuat menggunakan fetch akan selalu berjalan asynchronous.
Penggunaan dasar dari fetch tampak seperti ini:
20200313194951a9ddbc715b419aa9f5c19cfd5cb5ffae.png
Network request dilakukan pada saat fungsi fetch() tereksekusi.


  1. fetch("https://web-server-book-dicoding.appspot.com/list")


Jika request berhasil diproses oleh server, fungsi fetch() akan mengembalikan promise resolve dan membawa response object di dalamnya. 
Namun nilai response yang dibawa resolve belum sebagai data JSON yang kita butuhkan, melainkan informasi mengenai response itu sendiri, seperti status codetarget urlheaders, dsb. 
Maka dari itu, untuk mendapatkan data JSON yang dibutuhkan, kita perlu mengubah response object ke dalam bentuk JSON dengan memanggil method .json().


  1. fetch("https://web-server-book-dicoding.appspot.com/list")

  2.  .then(response => {

  3.    return response.json();

  4.  })


Method .json() juga mengembalikan nilai Promise, sehingga kita membutuhkan chaining promise dengan menambahkan .then() untuk mendapatkan data JSON yang sesungguhnya.


  1. fetch("https://web-server-book-dicoding.appspot.com/list")

  2.  .then(response => {

  3.    return response.json();

  4.  })

  5.  .then(responseJson => {

  6.    console.log(responseJson);

  7.  })


Lalu jangan lupa juga untuk menambahkan block catch() pada akhir chaining promise untuk menangani apabila rejected promise terjadi baik karena fungsi fetch() atau json().


  1. fetch("https://web-server-book-dicoding.appspot.com/list")

  2.  .then(response => {

  3.    return response.json();

  4.  })

  5.  .then(responseJson => {

  6.    console.log(responseJson);

  7.  })

  8.  .catch(error => {

  9.    console.log(error);

  10.  });


Karena fetch memanfaatkan promise, kita bisa memanfaatkan async/await jika Anda lebih suka dengan gaya penulisan synchronous.


  1. async function getBooks() {

  2.  try {

  3.    const response = await fetch("https://web-server-book-dicoding.appspot.com/list");

  4.    const responseJson = await response.json();

  5.    console.log(responseJson);

  6.  } catch (error) {

  7.    console.log(error);

  8.  }

  9. }

  10.  

  11. getBooks();



  1. fetch("https://web-server-book-dicoding.appspot.com/list")

  2.  .then(response => {

  3.    return response.json();

  4.  })

  5.  .then(responseJson => {

  6.    console.log(responseJson);

  7.  })

  8.  .catch(error => {

  9.    console.log(error);

  10.  });


Anda bisa mencoba jalankan potongan kode di atas menggunakan repl.it melalui tautan berikut: 

Advanced Fetch Usage

Fungsi fetch() dapat menerima dua buah parameter di dalamnya. 
Selain menetapkan target URL, kita juga dapat memberikan options untuk menetapkan methodheaderbody, dsb pada request yang akan dijalankan. Namun penerapan options ini bersifat pilihan. Tidak wajib.
2020031320004200d4bfb205c4a5469bb6063092d38d30.png
Penggunaan fetch() tanpa menerapkan options akan membuat GET request sederhana yang ditujukkan pada targetUrl
Hal tersebut sama seperti yang sudah kita lakukan sebelumnya. Lantas kapan kita perlu menerapkan options pada penggunaan fetch? Berikut beberapa kasus saat kita memerlukannya.

Changing Request Method

Untuk membuat POST request ataupun method request lainnya kita perlu menerapkan options dengan properti method di dalamnya.


  1. fetch("https://web-server-book-dicoding.appspot.com/add", {

  2.  method: "POST"

  3. })


Nilai dari properti method dituliskan dalam bentuk string, contohnya “POST”“PUT”“DELETE”, dsb. 
Nilai default dari properti ini adalah “GET”, sehingga jika kita membuat GET Request, kita tidak perlu menetapkan nilai method secara eksplisit.

Set Header Property

Untuk menambahkan request header dengan fetch kita gunakan properti headers pada options. Contohnya, untuk menambahkan properti Content-Type dengan nilai application/json pada headers kita dapat melakukannya dengan seperti ini:


  1. fetch("https://web-server-book-dicoding.appspot.com/add", {

  2.  method: "POST",

  3.  headers: {

  4.    "Content-Type": "application/json"

  5.  }

  6. })


Tentu kita juga dapat menetapkan lebih dari satu properti pada headers. Contohnya kita tambahkan lagi properti X-Auth-Token dengan nilai 12345.


  1. fetch("https://web-server-book-dicoding.appspot.com/add", {

  2.  method: "POST",

  3.  headers: {

  4.    "Content-Type": "application/json",

  5.    "X-Auth-Token": "12345"

  6.  }

  7. })


Set Data to Body Request

Untuk mengirimkan data pada body request kita gunakan properti body pada options, contohnya seperti ini:
  1. fetch(“https://web-server-book-dicoding.appspot.com/add”, {
  2.  method: “POST”,
  3.  headers: {
  4.    “Content-Type”: “application/json”,
  5.    “X-Auth-Token”: “12345”
  6.  },
  7.  body: JSON.stringify({
  8.    id: 10,
  9.    title: “Edensor”,
  10.    author: “Andrea Hirata”
  11.  })
  12. })
Sama seperti XHR, data yang dikirimkan melalui body request perlu diubah menjadi JSON String terlebih dahulu.


  1. body: JSON.stringify({

  2.    id: 10,

  3.    title: "Edensor",

  4.    author: "Andrea Hirata"

  5. })


Contoh kode di atas dapat Anda temukan pada tautan berikut https://repl.it/@dicodingacademy/163-06-AJAX-Fetch-Advanced?lite=true
Anda bisa coba lakukan POST Request menggunakan Fetch dengan menjalankan potongan kode tersebut

Latihan AJAX menggunakan Fetch

Kita sudah menerapkan AJAX pada proyek Dicoding Books dengan menggunakan XMLHttpRequest. Nah, Setelah mengetahui beberapa benefit dari fetch dibandingkan dengan XMLHttpRequest, mari ubah (refactor) fungsi yang sudah kita lengkapi seperti getBookinsertBookupdateBook dan deleteBook dengan menerapkan fetch.

Refactor fungsi getBook

Kita mulai dari fungsi getBook. Saat ini, fungsi getBook memiliki 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", `${baseUrl}/list`);

  21.     // Mengirimkan request

  22.     xhr.send();

  23. };


Ayo kita refactor fungsi tersebut dengan menerapkan fetch secara perlahan.
Langkah pertama, panggil fungsi fetch() di atas kode pembuatan instance xhr
Kemudian tuliskan target url yang merupakan kombinasi dari baseUrl dan endpoint sebagai parameternya.
  1. const getBook = () => {
  2.     fetch(`${baseUrl}/list`)
  3.     // membuat instance dari XMLHttpRequest
  4.     const xhr = new XMLHttpRequest();
  5. ….
Seperti yang sudah kita ketahui, fungsi fetch() akan mengembalikan promise resolve jika request berhasil dilakukan. Maka untuk menangani respon dari request yang dibuat, kita gunakan .then() yang di dalamnya berisi variabel response sebagai response object yang didapat.


  1. const getBook = () => {

  2.     fetch(`${baseUrl}/list`)

  3.      .then(response => {

  4.     

  5.      })

  6. ....


Kemudian di dalam blok then tersebut, kita ubah nilai response menjadi JSON dengan memanggil method response.json().


  1. const getBook = () => {

  2.     fetch(`${baseUrl}/list`)

  3.      .then(response => {

  4.          response.json();

  5.      })

  6. .....


Lalu kembalikan (return) blok then dengan nilai JSON tersebut,


  1. const getBook = () => {

  2.     fetch(`${baseUrl}/list`)

  3.      .then(response => {

  4.        return response.json();

  5.     })

  6. .....


Karena method response.json() juga mengembalikan nilai promise, maka untuk mendapatkan nilai yang dibawa oleh resolve kita perlu menambahkan .then lainnya (chaining promise). Di dalam .then yang kedua ini, berikan parameter dengan nama responseJson (penamaan variabel tidaklah baku, namun gunakan penamaan yang menunjukkan arti dari nilai variabelnya).


  1. const getBook = () => {

  2.     fetch(`${baseUrl}/list`)

  3.       .then(response => {

  4.           return response.json();

  5.        })

  6.        .then(responseJson => {

  7.              

  8.        })

  9. ....


responseJson merupakan nilai JSON yang dihasilkan dari perubahan object response dalam bentuk JSON melalui method .json() tadi.
Selanjutnya kita tuliskan logika yang sebelumnya berada di dalam callback xhr.onload ke dalam blok .then yang kedua.


  1. const getBook = () => {

  2.     fetch(`${baseUrl}/list`)

  3.      .then(response => {

  4.           return response.json();

  5.      })

  6.      .then(responseJson => {

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


Hapus baris kode berikut:


  1. const responseJson = JSON.parse(this.responseText);


Karena kita sudah tidak memerlukan pengubahan response ke JSON melalui JSON.parse().
Terakhir tambahkan method .catch() dengan parameter error pada akhir promise chaining, untuk menangani flow ketika terjadi promise rejection baik pada fetch() atau json().


  1. const getBook = () => {

  2.     fetch(`${baseUrl}/list`)

  3.      .then(response => {

  4.          return response.json();

  5.      })

  6.      .then(responseJson => {

  7.          if(responseJson.error) {

  8.             showResponseMessage(responseJson.message);

  9.          } else {

  10.             renderAllBooks(responseJson.books);

  11.          }

  12.      })

  13.      .catch(error => {

  14.              

  15.      })

  16. .......


Pada blok catch kita panggil fungsi showResponseMessage() dengan memberikan error sebagai parameter fungsinya.


  1. const getBook = () => {

  2.     fetch(`${baseUrl}/list`)

  3.      .then(response => {

  4.          return response.json();

  5.       })

  6.       .then(responseJson => {

  7.          if(responseJson.error) {

  8.              showResponseMessage(responseJson.message);

  9.          } else {

  10.              renderAllBooks(responseJson.books);

  11.          }

  12.       })

  13.       .catch(error => {

  14.            showResponseMessage(error);

  15.       })

  16.  

  17. .....


Penerapan fetch sudah selesai, yay! Kini u kita bisa menghapus kode pembuatan hingga pengiriman request menggunakan xhr dengan leluasa. Sehingga kode pada fungsi getBook akan tampak seperti ini:


  1. const getBook = () => {

  2.     fetch(`${baseUrl}/list`)

  3.      .then(response => {

  4.          return response.json();

  5.      })

  6.      .then(responseJson => {

  7.         if(responseJson.error) {

  8.             showResponseMessage(responseJson.message);

  9.         } else {

  10.             renderAllBooks(responseJson.books);

  11.         }

  12.      })

  13.      .catch(error => {

  14.          showResponseMessage(error);

  15.      })

  16. };


Simpan perubahan yang diterapkan, kemudian lihat hasilnya pada browser. Aplikasi Dicoding Books akan berfungsi sebagaimana mestinya.
Jika Anda lebih suka dengan gaya penulisan asynchronous pada promise, Anda bisa menggunakan async/await. Sehingga fungsi getBook tampak seperti ini:


  1. const getBook = async () => {

  2.     try {

  3.       const response = await fetch(`${baseUrl}/list`);

  4.       const responseJson = await response.json();

  5.       if(responseJson.error) {

  6.          showResponseMessage(responseJson.message);

  7.       } else {

  8.          renderAllBooks(responseJson.books);

  9.       }

  10.     } catch(error) {

  11.        showResponseMessage(error);

  12.     }

  13. }


Refactor fungsi insertBook

Selanjutnya kita refactor fungsi insertBook. Saat ini, fungsi insertBook memiliki 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 GET request dan menetapkan target URL
  17.     xhr.open(“POST”, `${baseUrl}/add`);
  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. };
Ayo kita refactor fungsi tersebut dengan menerapkan fetch secara perlahan.
Langkah pertama, panggil fungsi fetch() di atas kode pembuatan instance xhr. Kemudian tuliskan target url yang merupakan kombinasi dari baseUrl dan endpoint sebagai parameternya.


  1. const insertBook = (book) => {

  2.     fetch(`${baseUrl}/add`)

  3.     // Membuat instance dari XMLHttpRequest

  4.     const xhr = new XMLHttpRequest();

  5. ........


Karena pada fungsi insertBook kita menggunakan method request POST, maka kita perlu menetapkan options pada fungsi fetch seperti ini:


  1. const insertBook = (book) => {

  2.     fetch(`${baseUrl}/add`, {

  3.         method: "POST"

  4.     })

  5. …..


Lalu kita juga perlu menetapkan dua properti header yaitu Content-Type dengan nilai “application/json” dan X-Auth-Token dengan nilai “12345”, maka tambahkan properti headers pada options seperti ini:


  1. const insertBook = (book) => {

  2.     fetch(`${baseUrl}/add`, {

  3.         method: "POST",

  4.         headers: {

  5.            "Content-Type": "application/json",

  6.            "X-Auth-Token": "12345"

  7.         }

  8.     })

  9. ….


Selanjutnya kita pindahkan data body yang dikirimkan pada xhr melalui method .send() pada property body di dalam options.


  1. const insertBook = (book) => {

  2.     fetch(`${baseUrl}/add`, {

  3.         method: "POST",

  4.         headers: {

  5.             "Content-Type": "application/json",

  6.             "X-Auth-Token": "12345"

  7.         },

  8.         body: JSON.stringify(book)

  9.     })

  10. ....


Konfigurasi options sudah selesai! Selanjutnya untuk menangani respon dari request buatan kita, gunakan .then() yang di dalamnya berikan variabel response sebagai response object yang didapat.


  1. const insertBook = (book) => {

  2.     fetch(`${baseUrl}/add`, {

  3.         method: "POST",

  4.         headers: {

  5.             "Content-Type": "application/json",

  6.             "X-Auth-Token": "12345"

  7.         },

  8.         body: JSON.stringify(book)

  9.      })

  10.      .then(response => {

  11.  

  12.      })

  13. ......


Kemudian di dalam blok then tersebut, kita ubah nilai response menjadi JSON dengan memanggil method response.json().


  1. const insertBook = (book) => {

  2.     fetch(`${baseUrl}/add`, {

  3.         method: "POST",

  4.         headers: {

  5.             "Content-Type": "application/json",

  6.             "X-Auth-Token": "12345"

  7.         },

  8.         body: JSON.stringify(book)

  9.     })

  10.     .then(response => {

  11.         response.json();

  12.     })

  13. ......


Lalu kembalikan (return) blok then dengan nilai JSON tersebut.


  1. const insertBook = (book) => {

  2.     fetch(`${baseUrl}/add`, {

  3.         method: "POST",

  4.         headers: {

  5.             "Content-Type": "application/json",

  6.             "X-Auth-Token": "12345"

  7.         },

  8.         body: JSON.stringify(book)

  9.     })

  10.     .then(response => {

  11.         return response.json();

  12.     })

  13. ....


Sama seperti pada fungsi getBook, untuk mendapatkan nilai JSON yang dihasilkan response.json( ), kita juga perlu melakukan chaining promise dengan menambahkan then lainnya.


  1. const insertBook = (book) => {

  2.     fetch(`${baseUrl}/add`, {

  3.         method: "POST",

  4.         headers: {

  5.             "Content-Type": "application/json",

  6.             "X-Auth-Token": "12345"

  7.         },

  8.         body: JSON.stringify(book)

  9.     })

  10.     .then(response => {

  11.         return response.json();

  12.     })

  13.     .then(responseJson => {

  14.         

  15.     })

  16.  

  17. .....


Selanjutnya kita tuliskan logika yang sebelumnya berada di dalam callback xhr.onload ke dalam blok .then yang kedua.
  1. const insertBook = (book) => {
  2.     fetch(`${baseUrl}/add`, {
  3.         method: “POST”,
  4.         headers: {
  5.             “Content-Type”: “application/json”,
  6.             “X-Auth-Token”: “12345”
  7.         },
  8.         body: JSON.stringify(book)
  9.     })
  10.     .then(response => {
  11.         return response.json();
  12.     })
  13.     .then(responseJson => {
  14.         const responseJson = JSON.parse(this.responseText);
  15.         showResponseMessage(responseJson.message);
  16.         getBook();
  17.     })
  18.  
  19. ….
Hapus baris kode berikut:


  1. const responseJson = JSON.parse(this.responseText);


const responseJson = JSON.parse(this.responseText);
Karena kita sudah tidak memerlukan pengubahan response ke JSON melalui JSON.parse().
  1. const insertBook = (book) => {
  2.     fetch(`${baseUrl}/add`, {
  3.         method: “POST”,
  4.         headers: {
  5.             “Content-Type”: “application/json”,
  6.             “X-Auth-Token”: “12345”
  7.         },
  8.         body: JSON.stringify(book)
  9.     })
  10.     .then(response => {
  11.         return response.json();
  12.     })
  13.     .then(responseJson => {
  14.         const responseJson = JSON.parse(this.responseText);
  15.         showResponseMessage(responseJson.message);
  16.         getBook();
  17.     })
  18.  
  19. ….
Terakhir tambahkan method .catch() dengan parameter error pada akhir promise chaining, untuk menangani flow ketika terjadi promise rejection baik pada fetch() atau json().
  1. const insertBook = (book) => {
  2.     fetch(`${baseUrl}/add`, {
  3.         method: “POST”,
  4.         headers: {
  5.             “Content-Type”: “application/json”,
  6.             “X-Auth-Token”: “12345”
  7.         },
  8.         body: JSON.stringify(book)
  9.     })
  10.     .then(response => {
  11.         return response.json();
  12.     })
  13.     .then(responseJson => {
  14.         const responseJson = JSON.parse(this.responseText);
  15.         showResponseMessage(responseJson.message);
  16.         getBook();
  17.     })
  18.     .catch(error => {
  19.         showResponseMessage(error);
  20.     })
  21. ….
Penerapan fetch sudah selesai. Kita bisa menghapus kode pembuatan hingga pengiriman request menggunakan xhr dengan leluasa. Sehingga kode pada fungsi insertBook akan tampak seperti ini:
  1. const insertBook = (book) => {
  2.     fetch(`${baseUrl}/add`, {
  3.         method: “POST”,
  4.         headers: {
  5.             “Content-Type”: “application/json”,
  6.             “X-Auth-Token”: “12345”
  7.         },
  8.         body: JSON.stringify(book)
  9.     })
  10.     .then(response => {
  11.         return response.json();
  12.     })
  13.     .then(responseJson => {
  14.         showResponseMessage(responseJson.message);
  15.         getBook();
  16.     })
  17.     .catch(error => {
  18.         showResponseMessage(error);
  19.     })
  20. };
Simpan perubahan yang diterapkan, kemudian lihat hasilnya pada browser. Aplikasi Dicoding Books akan berfungsi sebagaimana mestinya.
Jika Anda lebih suka dengan gaya penulisan asynchronous pada promise, Anda bisa menggunakan async/await. Sehingga fungsi getBook tampak seperti ini:
  1. const insertBook = async (book) => {
  2.     try{
  3.         const options = {
  4.             method: “POST”,
  5.             headers: {
  6.                 “Content-Type”: “application/json”,
  7.                 “X-Auth-Token”: “12345”
  8.             },
  9.             body: JSON.stringify(book)
  10.         }
  11.  
  12.         const response = await fetch(`${baseUrl}/add`, options)
  13.         const responseJson = await response.json();
  14.         showResponseMessage(responseJson.message);
  15.         getBook();
  16.     } catch(error) {
  17.         showResponseMessage(error)
  18.     }
  19. }

Refactor fungsi updateBook

Selanjutnya kita refactor fungsi updateBook. Saat ini, fungsi updateBook memiliki 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 GET 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. };
Ayo kita refactor fungsi tersebut dengan menerapkan fetch secara perlahan.
Langkah pertama, panggil fungsi fetch() di atas kode pembuatan instance xhr
Kemudian tuliskan target url yang merupakan kombinasi dari baseUrl dan endpoint sebagai parameternya.

  1. const updateBook = (book) => {

  2.     fetch(`${baseUrl}/edit/${book.id}`)

  3.     // Membuat instance dari XMLHttpRequest

  4.     const xhr = new XMLHttpRequest();

  5. ....


Karena pada fungsi updateBook kita menggunakan method request PUT, maka kita perlu menetapkan options pada fungsi fetch seperti ini:


  1. const updateBook = (book) => {

  2.     fetch(`${baseUrl}/edit/${book.id}`, {

  3.          method: "PUT"

  4.      })

  5. ……….


Lalu kita juga perlu menetapkan dua properti header yaitu Content-Type dengan nilai “application/json” dan X-Auth-Token dengan nilai “12345”, maka tambahkan properti headers pada options seperti ini:


  1. const updateBook = (book) => {

  2.     fetch(`${baseUrl}/edit/${book.id}`, {

  3.          method: "PUT",

  4.          headers: {

  5.                 "Content-Type": "application/json",

  6.                 "X-Auth-Token": "12345"

  7.          }

  8.      })

  9. ……….


Selanjutnya kita pindahkan data body yang dikirimkan pada xhr melalui method .send() pada property body di dalam options.


  1. const updateBook = (book) => {

  2.     fetch(`${baseUrl}/edit/${book.id}`, {

  3.          method: "PUT",

  4.          headers: {

  5.                 "Content-Type": "application/json",

  6.                 "X-Auth-Token": "12345"

  7.          },

  8.          body: JSON.stringify(book)

  9.      })

  10. ……….


Konfigurasi options sudah selesai! Sisanya lakukan proses chaining promise sama seperti yang kita lakukan pada fungsi insertBook.
  1. const updateBook = (book) => {
  2.     fetch(`${baseUrl}/edit/${book.id}`, {
  3.          method: “PUT”,
  4.          headers: {
  5.                 “Content-Type”: “application/json”,
  6.                 “X-Auth-Token”: “12345”
  7.          },
  8.          body: JSON.stringify(book)
  9.      })
  10.      .then(response => {
  11.             return response.json();
  12.      })
  13.      .then(responseJson => {
  14.             showResponseMessage(responseJson.message);
  15.             getBook();
  16.      })
  17.      .catch(error => {
  18.             showResponseMessage(error);
  19.      })
  20. }
Penerapan fetch sudah selesai, dengan begitu kita bisa menghapus kode pembuatan hingga pengiriman request menggunakan xhr dengan leluasa. Sehingga kode pada fungsi updateBook akan tampak seperti ini:
  1. const updateBook = (book) => {
  2.     fetch(`${baseUrl}/edit/${book.id}`, {
  3.          method: “PUT”,
  4.          headers: {
  5.                 “Content-Type”: “application/json”,
  6.                 “X-Auth-Token”: “12345”
  7.          },
  8.          body: JSON.stringify(book)
  9.      })
  10.      .then(response => {
  11.             return response.json();
  12.      })
  13.      .then(responseJson => {
  14.             showResponseMessage(responseJson.message);
  15.             getBook();
  16.      })
  17.      .catch(error => {
  18.             showResponseMessage(error);
  19.      })
  20. };
Simpan perubahan yang diterapkan, kemudian lihat hasilnya pada browser. Aplikasi Dicoding Books akan berfungsi sebagaimana mestinya.
Jika Anda lebih suka dengan gaya penulisan asynchronous pada promise, Anda bisa menggunakan async/await. Sehingga fungsi updateBook tampak seperti ini:
  1. const updateBook = async (book) => {
  2.     try {
  3.         const options = {
  4.             method: “PUT”,
  5.             headers: {
  6.                “Content-Type”: “application/json”,
  7.                 “X-Auth-Token”: “12345”
  8.            },
  9.            body: JSON.stringify(book)
  10.         }
  11.     
  12.         const response = await fetch(`${baseUrl}/edit/${book.id}`, options);
  13.         const responseJson = await response.json();
  14.     
  15.         showResponseMessage(responseJson.message);
  16.         getBook();
  17.    } catch(error) {
  18.         showResponseMessage(error);
  19.    }
  20. };

Refactor fungsi deleteBook

Terakhir kita refactor fungsi deleteBook. Saat ini fungsi deleteBook memiliki 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. };
Ayo kita refactor fungsi tersebut dengan menerapkan fetch secara perlahan.
Langkah pertama, panggil fungsi fetch() di atas kode pembuatan instance xhr
Kemudian tuliskan target url yang merupakan kombinasi dari baseUrl dan endpoint sebagai parameternya.
  1. const removeBook = (bookId) => {
  2.     fetch(`${baseUrl}/delete/${bookId}`)
  3.         
  4.     // Membuat instance dari XMLHttpRequest
  5.     const xhr = new XMLHttpRequest();
  6. …..
Karena pada fungsi deleteBook kita menggunakan method request DELETE, maka kita perlu menetapkan options pada fungsi fetch seperti ini:

  1. const removeBook = (bookId) => {

  2.     fetch(`${baseUrl}/delete/${bookId}`, {

  3.             method: "DELETE"

  4.     })

  5. .....


Lalu kita juga perlu menetapkan dua properti header yaitu X-Auth-Token dengan nilai “12345.”  Kemudian tambahkan properti headers pada options seperti ini:
  1. const removeBook = (bookId) => {
  2.     fetch(`${baseUrl}/delete/${bookId}`, {
  3.             method: “DELETE”,
  4.             headers: {
  5.                 “X-Auth-Token”: “12345”
  6.             }
  7.     })
  8. …..
Konfigurasi options sudah selesai! Sisanya lakukan proses chaining promise sama seperti yang kita lakukan pada fungsi insertBook ataupun getBook.
  1. const removeBook = (bookId) => {
  2.     fetch(`${baseUrl}/delete/${bookId}`, {
  3.             method: “DELETE”,
  4.             headers: {
  5.                 “X-Auth-Token”: “12345”
  6.             }
  7.     })
  8.     .then(response => {
  9.         return response.json();
  10.     })
  11.     .then(responseJson => {
  12.         showResponseMessage(responseJson.message);
  13.         getBook();      
  14.     })
  15.     .catch(error => {
  16.         showResponseMessage(error);
  17.     })
  18.  
  19. ……
Penerapan fetch sudah selesai. Dengan begitu kita bisa menghapus kode pembuatan hingga pengiriman request menggunakan xhr dengan leluasa. Sehingga kode pada fungsi removeBook akan tampak seperti ini:
  1. const removeBook = (bookId) => {
  2.    fetch(`${baseUrl}/delete/${bookId}`, {
  3.         method: “DELETE”,
  4.         headers: {
  5.             “X-Auth-Token”: “12345”
  6.         }
  7.     })
  8.     .then(response => {
  9.         return response.json();
  10.     })
  11.     .then(responseJson => {
  12.         showResponseMessage(responseJson.message);
  13.         getBook();      
  14.     })
  15.     .catch(error => {
  16.         showResponseMessage(error);
  17.     })
  18. };
Simpan perubahan yang diterapkan, kemudian lihat hasilnya pada browser. Aplikasi Dicoding Books akan berfungsi sebagaimana mestinya.
Penerapan AJAX menggunakan Fetch dalam melengkapi fungsi yang ada di proyek 
Dicoding Books dapat Anda temukan juga pada repository berikut: https://github.com/dicodingacademy/a163-bfwd-labs/tree/303-dicoding-books-fetch
z
Asalas | Unlock Anime, Manhwa & Donghua Like Never BeforeFinasteriden: Unlock the Secrets of the Movie World!Marians Woman: Celebrating Beauty Around the WorldArheon - Unveiling the Secrets of Food & Origins WorldwideMPAPER The Ultimate Destination for Anime & Manga FansANMC21: Your Guide to Smarter Living and SuccessMV Agusta of Tampa: Your Automotive News HubTech and Play: Your Hub for Technology, Gaming, and GadgetsRebeccaSommer : Stories & Cultures from Around the WorldUETRABAJANDOJUNTOS - Inside the Music World’s Best-Kept SecretsVandelay Armor - Viral News and Global UpdatesGainesville Sun: Technology & Computers UnveiledGRFX Gaming Party Bus: Journey Through Gaming ErasHouse of Beauty: Celebrating the World's Most Beautiful WomenLearn Mistake: Wisdom for a Better LifeSports Hope Alive: Portal Olahraga DuniaWorld News TW - The Hottest Viral News & Global HeadlinesWriter Sujatha - Life Lessons & Struggles That Inspirehttps://128.199.185.186/https://143.198.89.74/https://165.227.47.178/https://170.64.208.214/https://170.64.192.239/https://46.101.102.216/LVONLINEtelegram lvonlinehttps://www.thecarbongenie.com/https://www.aievea-bijou.com/https://www.slashpolicy.com/https://www.benwestbeech.com/https://www.hh-bags.com/https://www.drupalforfacebook.org/https://www.lvonline.boats/https://www.lvoslot.com/https://www.lvobet.id/https://www.lvoslot.id/https://www.lvonline000.com/https://www.lvonline001.com/https://www.lvonline002.com/https://www.lvonline003.com/https://www.lvonline004.com/https://www.lvonline005.com/https://www.lvonline006.com/https://www.lvonline007.com/https://www.lvonline008.com/https://www.lvonline009.com/https://www.lvonline010.com/https://www.lvonlinepoker.com/https://www.lvonlinebola.com/https://www.lvonlinekasino.com/https://www.lvonline.io/https://www.lvonline.store/https://www.lvonline.online/https://www.situslvonline.us/situs bandar lvonlinehttps://146.190.97.83/https://143.198.209.134/https://188.166.246.204/https://167.172.83.179/https://togelhok.tv/https://www.togelhok.id/https://earthtoweb.com/https://www.elearningfacultymodules.org/https://www.how6youtoknowc.org/https://128.199.71.129/https://167.172.64.185/https://152.42.192.250/https://www.capcut88.com/https://www.capcut88.co/https://towsonsmiles.com/https://www.campur88.com/https://www.campur88.org/https://www.campur88.work/https://www.campur88.xyz/https://www.campur88.lol/https://www.nagacampur.biz/https://www.nagacampur.club/https://www.nagacampur.co/https://www.nagacampur.me/https://www.nagacampur.xyz/https://www.nasicampur88.com/https://165.232.175.185/https://152.42.164.228/https://152.42.194.203/https://152.42.169.214/https://www.campurslot.com/https://www.campurslot.id/https://www.campurslot.co/https://www.campurslot.org/https://www.campurslot.homes/https://www.campurslot.design/Badan Lembaga Pendidikan Ilmu Komputer SubangUniversitas Negeri JeparaLembaga Universitas Kristen MaranthaSMP 3 Negri Nganjukhttps://iklanmalay.com/https://promobola.comhttps://kapsychologists.comhttps://propertycloudsite.comSattar777 NewsVR Slot Online NewsRuby888 Online Slot NewsBerita Global Klik Agenslot228Agen Sloto SG777 NewsGold Club SlotOnline NewsAzar Marra Kech NewsBerita Sidney dan MancanegaraBerita Seputar Sumsel dan DuniaBerita Rehabilitasi Judi OnlineBerita Link Gacor TerupdateItalian Tuition News UpdateWPJS Online NewsBerita Agen Slot RoyalThai Slot Online NewsAll Online Game NewsOnline Game News UpdateAsian Lotre NewsBerita Demo Dana SlotBerita Kalbar ProvLocanda della Maria NewsWye Valley NewsBerita Agen Slot1004Berita Agen Slot33Agen Slot399 NewsPlayboy Slot Online NewsSlot Online BB Slot NewsSlot Online 911 News365 Slot Online NewsEat Atlah Newsambamali canadaInfo Seputar Sepakbolacentre thoughtBerita Hiburanopen etherpadras indo groupresistance manualPrediksi Shiowe want real newsthe poisoned pawnindonesia reclaimed teakswift kennedy and copullip passionmy passion foraim torontoPublic FlashesFriweb TeknologiIngenious Gamersthe late show gardensGishPuppy Newsslot danaOregon Farm Garden NewsViral Pulse GlobaljumpajpPromo Bola soccer Captivates The WorldKapsychologists World First The Science of Mental Health - Understanding Psychiatry: The Science of Mental HealthPropertyCloudSite How to Make Smarter Investments in Today’s MarketArnavichara Ultimate Guide Right Business SoftwareAuscare Disability A Comprehensive Guide to Retirement Homes Finding the Perfect Place to Enjoy Your Golden YearsSeries Mp4 The Future of Entertainment Streaming and Downloadable Video ExplainedAlogirlxinh How to Create a Successful Personal Page or Blog in 2024ihokibethttps://bengbulang-karangpucung.cilacapkab.go.id/https://comunicacion.unsa.edu.ar/https://seychellesbiodiversitychm.sc/https://www.925lms.com/https://www.guisseny.memoire.bzh/https://www.mobiliars.org/https://www.squashparkwieliczka.pl/
Asalas | Unlock Anime, Manhwa & Donghua Like Never BeforeFinasteriden: Unlock the Secrets of the Movie World!Marians Woman: Celebrating Beauty Around the WorldArheon - Unveiling the Secrets of Food & Origins WorldwideMPAPER The Ultimate Destination for Anime & Manga FansANMC21: Your Guide to Smarter Living and SuccessMV Agusta of Tampa: Your Automotive News HubTech and Play: Your Hub for Technology, Gaming, and GadgetsRebeccaSommer : Stories & Cultures from Around the WorldUETRABAJANDOJUNTOS - Inside the Music World’s Best-Kept SecretsVandelay Armor - Viral News and Global UpdatesGainesville Sun: Technology & Computers UnveiledGRFX Gaming Party Bus: Journey Through Gaming ErasHouse of Beauty: Celebrating the World's Most Beautiful WomenLearn Mistake: Wisdom for a Better LifeSports Hope Alive: Portal Olahraga DuniaWorld News TW - The Hottest Viral News & Global HeadlinesWriter Sujatha - Life Lessons & Struggles That Inspirehttps://128.199.185.186/https://143.198.89.74/https://165.227.47.178/https://170.64.208.214/https://170.64.192.239/https://46.101.102.216/LVONLINEtelegram lvonlinehttps://www.thecarbongenie.com/https://www.aievea-bijou.com/https://www.slashpolicy.com/https://www.benwestbeech.com/https://www.hh-bags.com/https://www.lvonline.boats/https://www.lvoslot.com/https://www.lvobet.id/https://www.lvoslot.id/https://www.lvonline000.com/https://www.lvonline001.com/https://www.lvonline002.com/https://www.lvonline003.com/https://www.lvonline004.com/https://www.lvonline005.com/https://www.lvonline006.com/https://www.lvonline007.com/https://www.lvonline008.com/https://www.lvonline009.com/https://www.lvonline010.com/https://www.lvonlinepoker.com/https://www.lvonlinebola.com/https://www.lvonlinekasino.com/https://www.lvonline.io/https://www.lvonline.store/https://www.lvonline.online/https://www.situslvonline.us/situs bandar lvonlinehttps://146.190.97.83/https://143.198.209.134/https://188.166.246.204/https://167.172.83.179/https://togelhok.tv/https://www.togelhok.id/https://earthtoweb.com/https://www.elearningfacultymodules.org/https://www.how6youtoknowc.org/https://128.199.71.129/https://167.172.64.185/https://152.42.192.250/https://www.capcut88.com/https://www.capcut88.co/https://towsonsmiles.com/https://www.campur88.com/https://www.campur88.org/https://www.campur88.work/https://www.campur88.xyz/https://www.campur88.lol/https://www.nagacampur.biz/https://www.nagacampur.club/https://www.nagacampur.co/https://www.nagacampur.me/https://www.nagacampur.xyz/https://www.nasicampur88.com/https://165.232.175.185/https://152.42.164.228/https://152.42.194.203/https://152.42.169.214/https://www.campurslot.com/https://www.campurslot.id/https://www.campurslot.co/https://www.campurslot.org/https://www.campurslot.homes/https://www.campurslot.design/Badan Lembaga Pendidikan Ilmu Komputer SubangUniversitas Negeri JeparaLembaga Universitas Kristen MaranthaSMP 3 Negri Nganjukhttps://iklanmalay.com/https://promobola.comhttps://kapsychologists.comhttps://propertycloudsite.comSattar777 NewsVR Slot Online NewsRuby888 Online Slot NewsBerita Global Klik Agenslot228Agen Sloto SG777 NewsGold Club SlotOnline NewsAzar Marra Kech NewsBerita Sidney dan MancanegaraBerita Seputar Sumsel dan DuniaBerita Rehabilitasi Judi OnlineBerita Link Gacor TerupdateItalian Tuition News UpdateWPJS Online NewsBerita Agen Slot RoyalThai Slot Online NewsAll Online Game NewsOnline Game News UpdateAsian Lotre NewsBerita Demo Dana SlotBerita Kalbar ProvLocanda della Maria NewsWye Valley NewsBerita Agen Slot1004Berita Agen Slot33Agen Slot399 NewsPlayboy Slot Online NewsSlot Online BB Slot NewsSlot Online 911 News365 Slot Online NewsEat Atlah Newsambamali canadaInfo Seputar Sepakbolacentre thoughtBerita Hiburanopen etherpadras indo groupresistance manualPrediksi Shiowe want real newsthe poisoned pawnindonesia reclaimed teakswift kennedy and copullip passionmy passion foraim torontoPublic FlashesFriweb TeknologiIngenious Gamersthe late show gardensGishPuppy Newsslot danaOregon Farm Garden NewsViral Pulse GlobaljumpajpPromo Bola soccer Captivates The WorldKapsychologists World First The Science of Mental Health - Understanding Psychiatry: The Science of Mental HealthPropertyCloudSite How to Make Smarter Investments in Today’s MarketArnavichara Ultimate Guide Right Business SoftwareAuscare Disability A Comprehensive Guide to Retirement Homes Finding the Perfect Place to Enjoy Your Golden YearsSeries Mp4 The Future of Entertainment Streaming and Downloadable Video ExplainedAlogirlxinh How to Create a Successful Personal Page or Blog in 2024ihokibethttps://bengbulang-karangpucung.cilacapkab.go.id/https://comunicacion.unsa.edu.ar/https://seychellesbiodiversitychm.sc/https://www.925lms.com/https://www.guisseny.memoire.bzh/https://www.mobiliars.org/https://www.squashparkwieliczka.pl/https://mok.edu.kz/https://www.mware.cloud/https://www.facilitiescoolingandheating.com.au/https://www.krillpay.ng/https://925worksuite.com/