Contents

วิธีปรับปรุงประสิทธิภาพการค้นหาในการโต้ตอบด้วยการดีเด้ง

ใน React เมื่อใช้ฟังก์ชันการค้นหา ตัวจัดการ onChange จะเรียกใช้ฟังก์ชันการค้นหาทุกครั้งที่ผู้ใช้พิมพ์ในช่องป้อนข้อมูล วิธีการนี้อาจทำให้เกิดปัญหาด้านประสิทธิภาพ โดยเฉพาะอย่างยิ่งหากทำการเรียก API หรือการสืบค้นฐานข้อมูล การเรียกใช้ฟังก์ชันการค้นหาบ่อยครั้งอาจทำให้เว็บเซิร์ฟเวอร์ทำงานหนักเกินไป ส่งผลให้เกิดข้อขัดข้องหรือ UI ที่ไม่ตอบสนอง การดีเด้งจะช่วยแก้ปัญหานี้ได้

การดีเด้งคืออะไร?

ในการใช้งานฟังก์ชันการค้นหาโดยทั่วไปใน React โดยทั่วไปเราจะเรียกใช้ฟังก์ชันตัวจัดการ onChange กับการกดแป้นพิมพ์แต่ละครั้ง ดังที่แสดงด้านล่าง:

 import { useState } from "react";

export default function Search() {
  const [searchTerm, setSearchTerm] = useState("");

  const handleSearch = () => {
    console.log("Search for:", searchTerm);
  };

  const handleChange = (e) => {
    setSearchTerm(e.target.value);
    // Calls search function
    handleSearch();
  };

  return (
    <input
      onChange={handleChange}
      value={searchTerm}
      placeholder="Search here..."/>
  );
}

เพื่อเพิ่มประสิทธิภาพการทำงาน สิ่งสำคัญคือต้องพิจารณาว่าการอัปเดตผลการค้นหาบ่อยครั้งผ่านการเรียกไปยังแบ็กเอนด์อาจมีค่าใช้จ่ายสูงเมื่อพิมพ์คำหลักเช่น “webdev” ในสถานการณ์นี้ แอปพลิเคชันจะส่งคำขอไปยังส่วนหลังทุกครั้งที่ป้อนอักขระใหม่ รวมถึงอักขระเช่น"w",“เรา”,“เว็บ"ฯลฯ

Debouncing เกี่ยวข้องกับการเลื่อนการดำเนินการของฟังก์ชันออกไปจนกว่ากรอบเวลาที่กำหนดจะผ่านไปนับตั้งแต่การเรียกใช้ครั้งล่าสุด ในสถานการณ์สมมตินี้ ฟังก์ชัน debounced จะถูกทริกเกอร์เมื่อผู้ใช้หยุดพิมพ์หลังจากช่วงเวลาที่ระบุเท่านั้น หากมีการป้อนข้อมูลเพิ่มเติมในช่วงเวลาที่กำหนด ตัวจับเวลาจะรีเซ็ตและเริ่มการประมวลผลอีกรอบ วงจรนี้จะเกิดซ้ำตราบใดที่ไม่มีการป้อนคีย์เพิ่มเติม และจะหยุดลงเมื่อผู้ใช้หยุดกิจกรรมการพิมพ์

การดีเด้งช่วยให้แอปพลิเคชันสามารถจัดการคำขอของเซิร์ฟเวอร์ได้อย่างมีประสิทธิภาพโดยชะลอคำขอเหล่านั้นจนกว่าผู้ใช้จะหยุดป้อนข้อมูล จึงช่วยลดการค้นหาที่ไม่จำเป็นและบรรเทาความเครียดบนเซิร์ฟเวอร์

วิธี Debounce การค้นหาใน React

เมื่อต้องการรวมฟังก์ชัน debouncing ในเว็บแอปพลิเคชัน มีไลบรารีที่มีอยู่แล้วหลายไลบรารีที่ให้ความสามารถนี้ อีกทางหนึ่งอาจเลือกที่จะสร้างอัลกอริธึม debouncer จากพื้นฐานโดยใช้เมธอด setTimeout และ clearTimeout ของ JavaScript

บทความนี้ใช้ฟังก์ชัน debouncing ที่จัดทำโดยไลบรารี Lodash ซึ่งเป็นยูทิลิตี JavaScript ยอดนิยมซึ่งมีฟังก์ชันการทำงานที่หลากหลายสำหรับการจัดการข้อมูลและการเพิ่มประสิทธิภาพการดำเนินงาน

เพื่อที่จะเริ่มต้นกระบวนการพัฒนาฟังก์ชันการค้นหาภายในโปรเจ็กต์ React ที่คุณมีอยู่หรือโดยการสร้างอันใหม่ จำเป็นต้องสร้างองค์ประกอบใหม่ชื่อ"Search"ก่อน ซึ่งสามารถทำได้โดยใช้แอปพลิเคชัน React ที่มีอยู่หรือใช้ยูทิลิตี้’สร้างแอป React’เพื่อสร้างสภาพแวดล้อม React ที่ทำงานได้อย่างสมบูรณ์

ในไฟล์ส่วนประกอบการค้นหา เราสามารถใช้ข้อมูลโค้ดที่ให้มาเพื่อสร้างฟิลด์อินพุตการค้นหาซึ่งจะดำเนินการฟังก์ชันเรียกกลับที่กำหนดทุกครั้งที่กดปุ่ม

 import { useState } from "react";

export default function Search() {
  const [searchTerm, setSearchTerm] = useState("");

  const handleSearch = () => {
    console.log("Search for:", searchTerm);
  };

  const handleChange = (e) => {
    setSearchTerm(e.target.value);
    // Calls search function
    handleSearch();
  };

  return (
    <input
      onChange={handleChange}
      value={searchTerm}
      placeholder="Search here..."/>
  );
}

หากต้องการชะลอการดำเนินการของฟังก์ชัน handleSearch โดยใช้ฟังก์ชัน debounce ที่จัดทำโดยไลบรารี Lodash เราสามารถส่งฟังก์ชันดังกล่าวเป็นอาร์กิวเมนต์ไปยังเมธอด debounce ได้ สิ่งนี้จะช่วยให้มั่นใจได้ว่าฟังก์ชันจะถูกดำเนินการเพียงครั้งเดียวในช่วงเวลาที่กำหนด หลังจากนั้นการโทรที่ตามมาภายในกรอบเวลานั้นจะถูกละเว้นจนกว่าระยะเวลารอจะสิ้นสุดลง

 import debounce from "lodash.debounce";
import { useState } from "react";

export default function Search() {
  const [searchTerm, setSearchTerm] = useState("");

  const handleSearch = () => {
    console.log("Search for:", searchTerm);
  };
  const debouncedSearch = debounce(handleSearch, 1000);

  const handleChange = (e) => {
    setSearchTerm(e.target.value);
    // Calls search function
    debouncedSearch();
  };

  return (
    <input
      onChange={handleChange}
      value={searchTerm}
      placeholder="Search here..."/>
  );
}

ในการดำเนินการตามกลไก debouncing เราขอแนะนำเวอร์ชันที่กำหนดเองของฟังก์ชัน handleSearch โดยการยอมรับเป็นอาร์กิวเมนต์พร้อมกับช่วงเวลาที่ระบุ ซึ่งก็คือ 500 มิลลิวินาที ซึ่งทำหน้าที่เป็นเกณฑ์ในการทริกเกอร์การดำเนินการล่าช้าของฟังก์ชันดังกล่าว.

โค้ดดังกล่าวคาดว่าจะเลื่อนการดำเนินการของฟังก์ชัน handleSearch ออกไปจนกว่าผู้ใช้จะสิ้นสุดการป้อนข้อมูล อย่างไรก็ตาม ฟังก์ชันนี้ไม่ทำงานตามที่ตั้งใจไว้ภายในกรอบงาน React สาเหตุของความคลาดเคลื่อนนี้จะมีการสำรวจเพิ่มเติมในส่วนถัดไป

การดีเด้งและการเรนเดอร์

แอปพลิเคชันปัจจุบันใช้อินพุตที่ได้รับการควบคุม โดยที่สภาพที่เป็นอยู่ของระบบจะกำหนดเนื้อหาที่ให้เป็นเอาต์พุตผ่านแถบค้นหา เมื่อผู้ใช้กดแป้นพิมพ์แต่ละครั้งภายในอินเทอร์เฟซเฉพาะนี้ React จะผนวกการแก้ไขการกำหนดค่าของสถานะตามนั้น

React เป็นไลบรารี JavaScript ยอดนิยมที่ใช้สำหรับสร้างส่วนต่อประสานกับผู้ใช้ เมื่อใดก็ตามที่ค่าสถานะในองค์ประกอบ React เปลี่ยนแปลง องค์ประกอบทั้งหมดจะถูกเรนเดอร์ใหม่ ซึ่งเกี่ยวข้องกับการเรียกใช้ฟังก์ชันทั้งหมดตั้งแต่ต้นจนจบอีกครั้ง ซึ่งช่วยให้สามารถอัปเดตแบบไดนามิกไปยังอินเทอร์เฟซได้โดยไม่จำเป็นต้องรีเฟรชทั้งหน้า

องค์ประกอบการค้นหาที่กล่าวมาข้างต้นได้รับการเรนเดอร์ใหม่ในระหว่างที่ React เปิดใช้งานกลไกการดีเด้ง ตัวจับเวลาแบบใหม่ถูกสร้างขึ้นเพื่อตรวจสอบความล่าช้าในขณะที่ตัวจับเวลาที่มีอยู่ยังคงทำงานอยู่ในหน่วยความจำระบบ เมื่อหมดอายุ ฟังก์ชันการค้นหาจะถูกกระตุ้นหลังจากถูกเลื่อนออกไปเป็นเวลา 500 มิลลิวินาที ด้วยเหตุนี้ ลำดับนี้จะเกิดขึ้นซ้ำเมื่อมีการเรนเดอร์แต่ละครั้ง เนื่องจากตัวจับเวลาใหม่มีความสำคัญมากกว่าลำดับก่อนหน้า โดยตัวจับเวลาเก่าจะสิ้นสุดระยะเวลาการยกเลิกในเวลาต่อมาก่อนที่จะเรียกใช้ฟังก์ชันการค้นหาซ้ำๆ

เพื่อให้แน่ใจว่าฟังก์ชัน debounced ทำงานตามที่ตั้งใจไว้ภายในส่วนประกอบ React สิ่งสำคัญคือต้องจำกัดการดำเนินการให้เหลือเพียงอินสแตนซ์เดียว แนวทางหนึ่งในการบรรลุเป้าหมายนี้เกี่ยวข้องกับการใช้เทคนิคการท่องจำร่วมกับฟังก์ชัน debouncing การทำเช่นนี้ แม้ว่าคอมโพเนนต์จะแสดงผลซ้ำ ฟังก์ชัน debounced จะไม่ถูกดำเนินการซ้ำๆ

การกำหนดฟังก์ชั่น Debounce ภายนอกองค์ประกอบการค้นหา

พิจารณาย้ายกลไกการดำเนินการที่เลื่อนออกไป เช่น debounce ไปยังตำแหน่งนอกคอมโพเนนต์ Search ดังแสดงในตัวอย่างที่ให้ไว้ด้านล่าง:

 import debounce from "lodash.debounce"

const handleSearch = (searchTerm) => {
  console.log("Search for:", searchTerm);
};

const debouncedSearch = debounce(handleSearch, 500);

ในการวนซ้ำปัจจุบันขององค์ประกอบการค้นหาของโปรเจ็กต์ของเรา เราจะใช้ฟังก์ชัน search ในเวอร์ชัน debounced โดยการเรียกใช้เมธอด debouncedSearch และจัดเตรียมคำค้นหาเป็นอาร์กิวเมนต์

 export default function Search() {
  const [searchTerm, setSearchTerm] = useState("");

  const handleChange = (e) => {
    setSearchTerm(e.target.value);
    // Calls search function
    debouncedSearch(searchTerm);
  };

  return (
    <input
      onChange={handleChange}
      value={searchTerm}
      placeholder="Search here..."/>
  );
}

ฟังก์ชันการทำงานของฟังก์ชันการค้นหาขึ้นอยู่กับการหมดอายุของช่วงเวลาที่กำหนดไว้ล่วงหน้า ซึ่ง ณ จุดนี้ฟังก์ชันดังกล่าวจะถูกเรียกใช้

จดจำฟังก์ชัน Debounce

การจำเกี่ยวข้องกับการจัดเก็บเอาต์พุตที่สร้างโดยฟังก์ชันเฉพาะเมื่อได้รับอินพุตเฉพาะ เพื่อให้สามารถเรียกค้นและใช้งานได้ทันทีหากฟังก์ชันถูกเรียกอีกครั้งด้วยพารามิเตอร์ที่เหมือนกัน เทคนิคนี้ใช้เป็นกลยุทธ์การปรับให้เหมาะสมเพื่อลดค่าใช้จ่ายในการคำนวณ โดยเฉพาะอย่างยิ่งในกรณีที่เกี่ยวข้องกับการคำนวณซ้ำ

หากต้องการแคชและเลื่อนการดำเนินการของฟังก์ชัน debounced อย่างมีประสิทธิภาพโดยใช้กลไก Memoization ของ React ให้ใช้ useMemo Hook ร่วมกับกลยุทธ์การใช้งานที่เหมาะสมสำหรับผล debouncing ที่ต้องการ

 import debounce from "lodash.debounce";
import { useCallback, useMemo, useState } from "react";

export default function Search() {
  const [searchTerm, setSearchTerm] = useState("");

  const handleSearch = useCallback((searchTerm) => {
    console.log("Search for:", searchTerm);
  }, []);

  const debouncedSearch = useMemo(() => {
    return debounce(handleSearch, 500);
  }, [handleSearch]);

  const handleChange = (e) => {
    setSearchTerm(e.target.value);
    // Calls search function
    debouncedSearch(searchTerm);
  };

  return (
    <input
      onChange={handleChange}
      value={searchTerm}
      placeholder="Search here..."/>
  );
}

สิ่งสำคัญคือต้องทราบว่าเราได้รวมฟังก์ชัน handleSearch ไว้ในฮุก useCallback เพื่อรับประกันว่า React จะเรียกใช้ฟังก์ชันนี้เพียงครั้งเดียวเท่านั้น หากไม่ใช่เพราะ hook useCallback React จะดำเนินการฟังก์ชัน handleSearch ซ้ำๆ ในระหว่างกระบวนการเรนเดอร์แต่ละครั้ง ส่งผลให้เกิดการเปลี่ยนแปลงการขึ้นต่อกันของ hook useMemo และผลที่ตามมาก็คือทริกเกอร์ฟังก์ชัน debounce

React จะเรียกใช้ฟังก์ชัน debounced เฉพาะในกรณีที่ฟังก์ชัน handleSearch หรือช่วงหน่วงเวลามีการเปลี่ยนแปลง

เพิ่มประสิทธิภาพการค้นหาด้วย Debounce

ในบางครั้ง การควบคุมความเร็วอาจนำไปสู่ประสิทธิภาพการผลิตที่เพิ่มขึ้น ในสถานการณ์ที่เกี่ยวข้องกับฐานข้อมูลหรือการสืบค้น API ที่มีราคาแพงในระหว่างดำเนินการค้นหา การใช้ฟังก์ชัน debounce จะต้องใช้ความระมัดระวัง ฟังก์ชันนี้กำหนดให้มีการหยุดชั่วคราวก่อนที่จะส่งต่อคำขอไปยังแบ็กเอนด์

การใช้กลไกการโหลดรูปภาพล่าช้าในหน้าเว็บสามารถแบ่งเบาภาระบนเซิร์ฟเวอร์ได้อย่างมาก โดยการจำกัดความถี่ของคำขอที่ส่งไปยังเซิร์ฟเวอร์เหล่านั้น ด้วยการกำหนดค่าระบบให้รอจนกว่าผู้ใช้จะหยุดอินพุตชั่วคราวก่อนส่งคำขอรูปภาพ เราจะลดปริมาณคำขอที่ประมวลผลพร้อมกันให้เหลือน้อยที่สุด ด้วยเหตุนี้ วิธีการนี้จึงรักษาประสิทธิภาพของเซิร์ฟเวอร์ให้เหมาะสมที่สุดในขณะเดียวกันก็ป้องกันการสิ้นเปลืองทรัพยากรหรือความล่าช้าในเวลาตอบสนอง