Rumah  >  Artikel  >  hujung hadapan web  >  Cara Membina Cangkuk Reaksi Yang Mengendalikan Permintaan Berurutan

Cara Membina Cangkuk Reaksi Yang Mengendalikan Permintaan Berurutan

WBOY
WBOYasal
2024-08-21 09:06:05691semak imbas

Apabila anda perlu bertindak balas dengan cepat terhadap tindakan pengguna dan mengambil data terkini dari bahagian belakang, anda mungkin memerlukan React Hook yang menyokong permintaan berjujukan. Cangkuk ini boleh membatalkan permintaan sebelumnya jika ia masih berterusan dan hanya mengembalikan data terbaharu. Ini bukan sahaja meningkatkan prestasi tetapi juga meningkatkan pengalaman pengguna.

Membina Cangkuk Reaksi Permintaan Berjujukan Mudah

Mari mulakan dengan membina permintaan berurutan yang ringkas React hook:

import { useCallback, useRef } from 'react';
​
const buildCancelableFetch = <T>(
  requestFn: (signal: AbortSignal) => Promise<T>,
) => {
  const abortController = new AbortController();
​
  return {
    run: () =>
      new Promise<T>((resolve, reject) => {
        if (abortController.signal.aborted) {
          reject(new Error('CanceledError'));
          return;
        }
​
        requestFn(abortController.signal).then(resolve, reject);
      }),
​
    cancel: () => {
      abortController.abort();
    },
  };
};
​
function useLatest<T>(value: T) {
  const ref = useRef(value);
  ref.current = value;
  return ref;
}
​
export function useSequentialRequest<T>(
  requestFn: (signal: AbortSignal) => Promise<T>,
) {
  const requestFnRef = useLatest(requestFn);
  const currentRequest = useRef<{ cancel: () => void } | null>(null);
​
  return useCallback(async () => {
    if (currentRequest.current) {
      currentRequest.current.cancel();
    }
​
    const { run, cancel } = buildCancelableFetch(requestFnRef.current);
    currentRequest.current = { cancel };
​
    return run().finally(() => {
      if (currentRequest.current?.cancel === cancel) {
        currentRequest.current = null;
      }
    });
  }, [requestFnRef]);
}

Idea utama di sini datang daripada artikel "Cara Membatalkan Janji dalam JavaScript." Anda boleh menggunakannya seperti ini:

import { useSequentialRequest } from './useSequentialRequest';
​
export function App() {
  const run = useSequentialRequest((signal: AbortSignal) =>
    fetch('http://localhost:5000', { signal }).then((res) => res.text()),
  );
​
  return <button onClick={run}>Run</button>;
}

Dengan cara ini, apabila anda mengklik butang dengan cepat beberapa kali, anda hanya akan mendapat data daripada permintaan terkini dan permintaan sebelumnya akan dibuang.

How to Build a React Hook That Handles Sequential Requests

Membina Cangkuk Reaksi Permintaan Urutan Dioptimumkan

Jika kami memerlukan permintaan berurutan yang lebih komprehensif React Hook, terdapat ruang untuk penambahbaikan dalam kod di atas. Contohnya:

  • Kami boleh menangguhkan pembuatan AbortController sehingga ia benar-benar diperlukan, mengurangkan kos penciptaan yang tidak perlu.

  • Kami boleh menggunakan generik untuk menyokong sebarang jenis hujah permintaan.

Berikut ialah versi yang dikemas kini:

import { useCallback, useRef } from 'react';
​
function useLatest<T>(value: T) {
  const ref = useRef(value);
  ref.current = value;
  return ref;
}
​
export function useSequentialRequest<Args extends unknown[], Data>(
  requestFn: (signal: AbortSignal, ...args: Args) => Promise<Data>,
) {
  const requestFnRef = useLatest(requestFn);
​
  const running = useRef(false);
  const abortController = useRef<AbortController | null>(null);
​
  return useCallback(
    async (...args: Args) => {
      if (running.current) {
        abortController.current?.abort();
        abortController.current = null;
      }
​
      running.current = true;
​
      const controller = abortController.current ?? new AbortController();
      abortController.current = controller;
​
      return requestFnRef.current(controller.signal, ...args).finally(() => {
        if (controller === abortController.current) {
          running.current = false;
        }
      });
    },
    [requestFnRef],
  );
}

Perhatikan bahawa dalam blok akhirnya, kami menyemak sama ada pengawal semasa sama dengan abortController.current untuk mengelakkan keadaan perlumbaan. Ini memastikan bahawa hanya permintaan aktif boleh mengubah suai keadaan berjalan.

Penggunaan Lebih Komprehensif:

import { useState } from 'react';
import { useSequentialRequest } from './useSequentialRequest';
​
export default function Home() {
  const [data, setData] = useState('');
​
  const run = useSequentialRequest(async (signal: AbortSignal, query: string) =>
    fetch(`/api/hello?query=${query}`, { signal }).then((res) => res.text()),
  );
​
  const handleInput = async (queryStr: string) => {
    try {
      const res = await run(queryStr);
      setData(res);
    } catch {
      // ignore errors
    }
  };
​
  return (
    <>
      <input
        placeholder="Please input"
        onChange={(e) => {
          handleInput(e.target.value);
        }}
      />
      <div>Response Data: {data}</div>
    </>
  );
}

Anda boleh mencubanya dalam talian: semasa anda menaip dengan cepat, permintaan sebelumnya akan dibatalkan dan hanya respons terkini akan ditunjukkan.

How to Build a React Hook That Handles Sequential Requests


Jika anda mendapati ini membantu, sila pertimbangkan untuk melanggan kepada surat berita saya untuk artikel dan alatan yang lebih berguna tentang pembangunan web. Terima kasih kerana membaca!

Atas ialah kandungan terperinci Cara Membina Cangkuk Reaksi Yang Mengendalikan Permintaan Berurutan. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn