"إذا أراد العامل أن يؤدي عمله بشكل جيد، فعليه أولاً أن يشحذ أدواته." - كونفوشيوس، "مختارات كونفوشيوس. لو لينجونج"
الصفحة الأمامية > برمجة > كيفية بناء خطاف تفاعلي يتعامل مع الطلبات المتسلسلة

كيفية بناء خطاف تفاعلي يتعامل مع الطلبات المتسلسلة

تم النشر بتاريخ 2024-11-04
تصفح:462

عندما تحتاج إلى الاستجابة بسرعة لإجراءات المستخدم وجلب أحدث البيانات من الواجهة الخلفية، فقد تحتاج إلى React Hook الذي يدعم الطلبات التسلسلية. يمكن لهذا الخطاف إلغاء الطلبات السابقة إذا كانت لا تزال مستمرة ويعيد فقط أحدث البيانات. وهذا لا يؤدي إلى تحسين الأداء فحسب، بل يعزز أيضًا تجربة المستخدم.

بناء خطاف رد فعل طلب تسلسلي بسيط

لنبدأ ببناء طلب تسلسلي بسيط، خطاف التفاعل:

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

الفكرة الأساسية هنا تأتي من مقالة "كيفية إلغاء الوعود في جافا سكريبت". يمكنك استخدامه مثل هذا:

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

بهذه الطريقة، عند النقر فوق الزر بسرعة عدة مرات، ستحصل فقط على البيانات من الطلب الأخير، وسيتم تجاهل الطلبات السابقة.

How to Build a React Hook That Handles Sequential Requests

إنشاء خطاف تفاعل للطلبات التسلسلية المُحسّنة

إذا كنا بحاجة إلى React Hook لطلب تسلسلي أكثر شمولاً، فهناك مجال للتحسين في الكود أعلاه. على سبيل المثال:

  • يمكننا تأجيل إنشاء AbortController حتى تكون هناك حاجة إليه فعليًا، مما يقلل تكاليف الإنشاء غير الضرورية.

  • يمكننا استخدام الأدوية العامة لدعم أي نوع من وسائط الطلب.

إليك الإصدار المحدث:

import { useCallback, useRef } from 'react';
​
function useLatest(value: T) {
  const ref = useRef(value);
  ref.current = value;
  return ref;
}
​
export function useSequentialRequest(
  requestFn: (signal: AbortSignal, ...args: Args) => Promise,
) {
  const requestFnRef = useLatest(requestFn);
​
  const running = useRef(false);
  const abortController = useRef(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],
  );
}

لاحظ أنه في الكتلة الأخيرة، نتحقق مما إذا كانت وحدة التحكم الحالية تساوي abortController.current لمنع حالات السباق. وهذا يضمن أن الطلب النشط فقط يمكنه تعديل حالة التشغيل.

استخدام أكثر شمولاً:

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 (
    
       {
          handleInput(e.target.value);
        }}
      />
      
Response Data: {data}
> ); }

يمكنك تجربتها عبر الإنترنت: أثناء الكتابة بسرعة، سيتم إلغاء الطلبات السابقة، وسيتم عرض الرد الأخير فقط.

How to Build a React Hook That Handles Sequential Requests


إذا وجدت هذا مفيدًا، يرجى الاشتراك في في النشرة الإخبارية الخاصة بي للحصول على المزيد من المقالات والأدوات المفيدة حول تطوير الويب. شكرا على القراءة!

بيان الافراج تم إعادة إنتاج هذه المقالة على: https://dev.to/zacharylee/how-to-build-a-react-hook-that-handles-sequential-requests-e49?1 إذا كان هناك أي انتهاك، يرجى الاتصال بـ Study_golang@163 .com لحذفه
أحدث البرنامج التعليمي أكثر>

تنصل: جميع الموارد المقدمة هي جزئيًا من الإنترنت. إذا كان هناك أي انتهاك لحقوق الطبع والنشر الخاصة بك أو الحقوق والمصالح الأخرى، فيرجى توضيح الأسباب التفصيلية وتقديم دليل على حقوق الطبع والنشر أو الحقوق والمصالح ثم إرسالها إلى البريد الإلكتروني: [email protected]. سوف نتعامل مع الأمر لك في أقرب وقت ممكن.

Copyright© 2022 湘ICP备2022001581号-3