Rumah > Artikel > hujung hadapan web > Cara Membina Cangkuk Reaksi Yang Mengendalikan Permintaan Berurutan
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.
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.
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.
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!