news

Jumat, 12 Juni 2020

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