Membatalkan Permintaan JavaScript

Jan 07 2023
Bagi siapa pun yang bekerja untuk menjembatani kesenjangan antara backend, atau sisi server, aplikasi web dan frontend, atau sisi browser, aplikasi web mengetahui ada dua opsi populer modern untuk interaksi dengan protokol respons permintaan, lebih dikenal sebagai http(s)¹. Opsi utama tersebut adalah Fetch API², yang merupakan metode JavaScript bawaan baru yang dibuat berdasarkan promise, dan Axios API, library add-on opsional yang juga berbasis promise.

Bagi siapa pun yang bekerja untuk menjembatani kesenjangan antara backend, atau sisi server, aplikasi web dan frontend, atau sisi browser, aplikasi web mengetahui ada dua opsi populer modern untuk interaksi dengan protokol respons permintaan, lebih dikenal sebagai http(s)¹. Opsi utama tersebut adalah Fetch API ², yang merupakan metode JavaScript bawaan baru yang dibuat berdasarkan promise, dan Axios API , pustaka add-on opsional yang juga berbasis promise.

Ada banyak perbandingan dan pemahaman yang harus dilakukan antara keduanya saat memulai proyek baru untuk menentukan mana yang lebih sesuai dengan kebutuhan proyek, tetapi itu tidak akan menjadi fokus di sini. Proyek yang saya kerjakan sudah menyertakan dan menggunakan Axios, jadi meskipun saya dapat memilih salah satu perpustakaan karena saya ingin tetap menggunakan Axios.

Saya sedang membangun antarmuka frontend untuk pemangku kepentingan bisnis untuk menanyakan database kami dan melihat hasilnya dalam tabel yang dirancang dengan cermat. Karena jumlah dan kerumitan kueri, permintaan data ini dapat memerlukan waktu beberapa detik untuk dijalankan. Selain itu, ada banyak cara untuk memfilter dan mencari informasi yang dibutuhkan, menciptakan kemungkinan untuk menjalankan beberapa permintaan, karena permintaan baru dikirim setiap kali pengguna menggunakan filter atau istilah pencarian untuk membuatnya. Jadi kebutuhan awal untuk mengirim permintaan dan menerima tanggapan mudah diselesaikan. Namun, dengan penerapan yang sangat mendasar ini dan kemungkinan menggunakan banyak filter, yang menghasilkan banyak permintaan, menyebabkan kelambatan dalam menampilkan informasi permintaan terbaru.

Masalahnya sekarang menjadi terlalu banyak permintaan yang dibuat dan simpanan respons yang dikirim ke UI yang tidak perlu ditampilkan. Kebutuhan telah menyempit menjadi cara untuk membatasi permintaan atau hanya menampilkan permintaan terakhir, ketika pengguna telah menyelesaikan pencarian dan memfilter pilihan untuk kueri tingkat lanjut. Oke, jadi bagaimana penerapannya?

Salah satu kemungkinan pertama yang terlintas dalam pikiran adalah menggunakan event listener di komponen UI untuk menunggu hingga pengguna selesai memilih filter dan mencari. Setelah direnungkan lebih lanjut, ini adalah ide yang cukup naif dan penerapannya akan menjadi rumit tanpa perlu. Ada beberapa komponen UI yang perlu didengarkan, dan mencoba menebak mana yang akan didengarkan, dan berapa lama menunggu setelahnya sepertinya tidak mungkin. Itu juga masih tidak akan menyelesaikan masalah berjalan lama, kueri kompleks masih perlu dikembalikan dan dirender sebelum pilihan baru dibuat. Kemungkinan lain yang lebih masuk akal adalah menghentikan kueri sebelumnya menyelesaikan responsnya dan hanya mengembalikan kueri saat ini. Jadi, apakah ini mungkin dan bagaimana caranya?

Ternyata itu mungkin. Dengan membatalkan permintaan. Karena dibuat dengan janji Javascript, dimungkinkan untuk membatalkan permintaan dengan Fetch dan Axios. Masalah ini menyenangkan untuk dipecahkan karena tidak ada banyak artikel di luar sana, tidak seperti topik populer lainnya. Itu juga tercakup dengan baik dan dokumentasi Axios yang hebat menghasilkan pengujian dan implementasi yang cepat. Jadi, jika Anda tertarik dengan cara membatalkan permintaan Ambil, lihat artikel ini , jika tidak, jika Anda tertarik dengan cara membatalkan permintaan Axios dan bagaimana saya melakukannya, teruskan membaca!

Penafian cepat: Saya awalnya mengalami masalah ini dan memulai garis besar untuk ini beberapa waktu lalu, dan berjalan di Axios v.0.21.1. Saya melihat bahwa sejak itu, dalam versi minor berikutnya, penerapannya telah berubah, yang berarti waktu untuk bonus refactor di artikel lain!

Tapi pertama-tama, saya akan menjalankan pendekatan untuk solusi asli. Seperti yang dinyatakan sebelumnya, saya tidak menemukan terlalu banyak artikel atau pendekatan langkah demi langkah untuk mengimplementasikan pembatalan permintaan Axios, namun tim di sana memiliki dokumentasi yang sangat baik . Jadi, saya membuat eksperimen kecil cepat untuk menguji membatalkan permintaan saya sendiri, yang akan saya dapatkan setelah sedikit latar belakang tambahan.

Untuk latar belakang tambahan pada proyek, itu adalah proyek lama Ruby on Rails yang perlahan-lahan diubah menjadi hanya API dengan frontend React. Jadi untuk bukti pengujian konsep yang mudah, pertama-tama saya ingin mencoba menekan API Rails, dan kemudian mencari cara untuk menyambungkannya ke aplikasi React kustom kami.

Penafian nomor 2: Saya sangat suka mempelajari hal-hal baru dengan berpasangan dengan orang lain. Jauh lebih menyenangkan untuk mencari tahu sesuatu dengan pasangan, terutama karena ketika mempelajari sesuatu yang baru, sangat mudah untuk kewalahan dan membuat kesalahan atau melewatkan langkah sederhana, yang kemungkinan kecil terjadi dengan pandangan lain! Jadi, pada titik tertentu dari proses penyelesaian masalah ini, "Saya" menjadi "kita", sebentar sebelum saya pergi solo lagi, dan saya akan sangat menyarankan untuk menangani ini atau hal baru lainnya dengan seorang teman juga!

Bunyinya seperti ini — di aplikasi Rails kami:

  1. Tambahkan tampilan ke pengontrol. Kami tahu bahwa kami ingin menguji beberapa permintaan yang memerlukan waktu penyelesaian yang berbeda untuk melihat apakah kami dapat membatalkan salah satu, atau keduanya. Kemudian kami berhipotesis mana yang akan dirender dan menguji hasil mana yang sebenarnya dirender. Kami menambahkan metode penghitung waktu untuk mensimulasikan respons yang membutuhkan waktu ekstra untuk dihitung.
  2. def lol
      if params[:wat] == '1'
        sleep 1
        render json: '"one"'
      else
        render json: '"two"'
      end
    end
    

    get '/lol', to: "view#lol"
    

    const axios = require('axios');
    const CancelToken = axios.CancelToken;
    const source1 = CancelToken.source();
    const source2 = CancelToken.source();
    axios.get('http://localhost:3001/v0/lol?wat=1', {
      // set the token
      cancelToken: source1.token
    }).then(response => {
      // log response
      console.log('response 1', response.data)
    }).catch(function (thrown) {
      if (axios.isCancel(thrown)) {
        // log request if canceled
        console.log('Request 1 canceled', thrown.message);
      } else {
        // handle error
        console.log('failed 1', thrown)
      }
    });
    // cancel the request with a message
    source1.cancel('Operation canceled by the user.');
    axios.get('http://localhost:3001/v0/lol?wat=2', {
      cancelToken: source2.token
    }).then(response => {
      console.log('response 2', response.data)
    }).catch(function (thrown) {
      if (axios.isCancel(thrown)) {
        console.log('Request 2 canceled', thrown.message);
      } else {
        console.log('failed 2', thrown)
      }
    });
    

.catch(error => {
  if (axios.isCancel(error)) {
    // Cancel request without dispatching an actual error.
    return;
  }
}

export default async function request(
path,
method,
{ body, headers, baseUrl, params, withCredentials = true, cancelToken } = {}
) { .... }

const [cancelToken, setCancelToken] = useState();
const { data, isLoading, error, request } = usePromise(() => {
  // For every new request made, the previous request is canceled.
  cancelToken?.cancel('Newer request made.');
const tokenSource = axios.CancelToken.source();
setCancelToken(tokenSource);
return getRequest(filter, page, 20, tokenSource.token);
}, {
  effectCondition: [page, filter],
  isEffect: true,
});

Bonus: refactor!

  1. The 's' berarti aman. Aman karena data yang dikirim bolak-balik pada koneksi dienkripsi untuk https dan hanya berupa teks biasa melalui http.
  2. Fetch menjadi standar API baru yang dibangun dari XMLHttpRequest , yang juga digunakan Axios di bawah tenda.