ช่วงทดลองใช้จากต้นทางAPI ของFetchLater

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

เดิมทีนักพัฒนาซอฟต์แวร์ใช้เหตุการณ์ pagehide และ visibilitychange เพื่อจับหน้าเว็บขณะที่ระบบยกเลิกการโหลด จากนั้นใช้ navigator.sendBeacon() หรือ fetch() ที่มี keepalive เพื่อส่งข้อมูลบีคอน อย่างไรก็ตาม เหตุการณ์ทั้ง 2 รายการนี้มีปัญหาเฉพาะที่ยากซึ่งแตกต่างกันไปตามเบราว์เซอร์ของผู้ใช้ และบางครั้งเหตุการณ์อาจไม่เกิดขึ้นเลย โดยเฉพาะบนอุปกรณ์เคลื่อนที่

fetchLater() คือข้อเสนอที่จะแทนที่ความซับซ้อนนี้ด้วยการเรียก API เพียงครั้งเดียว ซึ่งทํางานตามที่ชื่อบอกไว้ทุกประการ กล่าวคือจะขอให้เบราว์เซอร์ส่งคําขอในอนาคต ณ เวลาใดเวลาหนึ่ง แม้ว่าหน้าเว็บจะปิดอยู่หรือผู้ใช้จะไปยังหน้าอื่นแล้วก็ตาม

fetchLater() พร้อมใช้งานใน Chrome สำหรับการทดสอบกับผู้ใช้จริงในช่วงทดลองใช้จากต้นทางตั้งแต่เวอร์ชัน 121 (เปิดตัวในเดือนมกราคม 2024) จนถึงวันที่ 3 กันยายน 2024

fetchLater() API

const fetchLaterResult = fetchLater(request, options);

fetchLater() ใช้อาร์กิวเมนต์ 2 รายการ ซึ่งโดยทั่วไปจะเหมือนกับของ fetch() ดังนี้

  • request ซึ่งอาจเป็น URL สตริงหรืออินสแตนซ์ Request
  • ออบเจ็กต์ options ที่ไม่บังคับ ซึ่งขยาย options จาก fetch() ด้วยระยะหมดเวลาที่เรียกว่า activateAfter

fetchLater() จะแสดงผล FetchLaterResult ซึ่งมีพร็อพเพอร์ตี้ activated แบบอ่านอย่างเดียวรายการเดียวในปัจจุบัน ซึ่งจะตั้งค่าเป็น true เมื่อ "ภายหลัง" ผ่านไปแล้วและดึงข้อมูลแล้ว ระบบจะทิ้งการตอบกลับคำขอ fetchLater()

request

การใช้งานที่ง่ายที่สุดคือ URL เพียงอย่างเดียว

fetchLater('/endpoint/');

แต่เช่นเดียวกับ fetch() คุณสามารถตั้งค่าตัวเลือกจํานวนมากในคําขอ fetchLater() ซึ่งรวมถึงส่วนหัวที่กําหนดเอง ลักษณะการทํางานของข้อมูลเข้าสู่ระบบ POST body และ AbortController signal เพื่อยกเลิกคําขอได้

fetchLater('/endpoint/', {
  method: 'GET',
  cache: 'no-store',
  mode: 'same-origin',
  headers: {Authorization: 'SUPER_SECRET'},
});

options

ออบเจ็กต์ options จะขยายตัวเลือกของ fetch() ด้วย activateAfter ซึ่งเป็นการหมดเวลา ในกรณีที่คุณต้องการเรียกใช้คําขอหลังจากหมดเวลาหรือเมื่อระบบยกเลิกการโหลดหน้าเว็บแล้วแต่ว่าเหตุการณ์ใดจะเกิดขึ้นก่อน

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

ตัวอย่างเช่น หากคุณมีแอปที่ผู้ใช้มักจะเปิดไว้ตลอดทั้งวันทําการ คุณอาจต้องการตั้งค่าการหมดเวลาเป็น 1 ชั่วโมงเพื่อให้ได้ข้อมูลวิเคราะห์ที่ละเอียดยิ่งขึ้น ในขณะเดียวกันก็ยังคงรับประกันบีคอนได้หากผู้ใช้ออกจากแอปเมื่อใดก็ได้ก่อนที่เวลา 1 ชั่วโมงจะหมด จากนั้นตั้งค่า fetchLater() ใหม่สําหรับการวิเคราะห์ชั่วโมงถัดไปได้

const hourInMilliseconds = 60 * 60 * 1000;
fetchLater('/endpoint/', {activateAfter: hourInMilliseconds});

ตัวอย่างการใช้งาน

ปัญหาอย่างหนึ่งในการวัด Core Web Vitals ภาคสนามคือเมตริกประสิทธิภาพใดๆ ก็อาจเปลี่ยนแปลงได้จนกว่าผู้ใช้จะออกจากหน้าเว็บ เช่น การเปลี่ยนเลย์เอาต์ขนาดใหญ่อาจเกิดขึ้นได้ทุกเมื่อ หรือหน้าเว็บอาจใช้เวลาในการตอบสนองต่อการโต้ตอบนานขึ้น

อย่างไรก็ตาม คุณไม่ต้องการเสี่ยงที่จะสูญเสียข้อมูลประสิทธิภาพทั้งหมดเนื่องจากบีคอนทำงานผิดพลาดหรือไม่สมบูรณ์เมื่อหน้าเว็บปิด เหมาะสำหรับ fetchLater()

ในตัวอย่างนี้ ระบบจะใช้ไลบรารี web-vitals.js เพื่อตรวจสอบเมตริก และ fetchLater() เพื่อรายงานผลลัพธ์ไปยังปลายทางข้อมูลวิเคราะห์

import {onCLS, onINP, onLCP} from 'web-vitals';

const queue = new Set();
let fetchLaterController;
let fetchLaterResult;

function updateQueue(metricUpdate) {
  // If there was an already complete request for whatever
  // reason, clear out the queue of already-sent updates.
  if (fetchLaterResult?.activated) {
    queue.clear();
  }

  queue.add(metricUpdate);

  // JSON.stringify used here for simplicity and will likely include
  // more data than you need. Replace with a preferred serialization.
  const body = JSON.stringify([...queue]);

  // Abort any existing `fetchLater()` and schedule a new one with
  // the update included.
  fetchLaterController?.abort();
  fetchLaterController = new AbortController();
  fetchLaterResult = fetchLater('/analytics', {
    method: 'POST',
    body,
    signal: fetchLaterController.signal,
    activateAfter: 60 * 60 * 1000, // Timeout to ensure timeliness.
  });
}

onCLS(updateQueue);
onINP(updateQueue);
onLCP(updateQueue);

ทุกครั้งที่มีข้อมูลอัปเดตเมตริก ระบบจะยกเลิกfetchLater()ที่ตั้งเวลาไว้ที่มีอยู่ด้วย AbortController และสร้างfetchLater()ใหม่โดยรวมข้อมูลอัปเดตนั้น

ลองใช้ fetchLater()

ตามที่ได้แจ้งไว้ก่อนหน้านี้ fetchLater() มีให้บริการในช่วงทดลองใช้จากต้นทางจนถึง Chrome 126 ดูข้อมูลเบื้องต้นเกี่ยวกับการทดลองใช้ต้นทางได้ที่ "เริ่มต้นใช้งานการทดลองใช้ต้นทาง"

สําหรับการทดสอบในเครื่อง คุณสามารถเปิดใช้ fetchLater ได้ด้วยการตั้งค่า Flag ฟีเจอร์แพลตฟอร์มเว็บเวอร์ชันทดลองที่ chrome://flags/#enable-experimental-web-platform-features นอกจากนี้ คุณยังเปิดใช้ได้โดยเรียกใช้ Chrome จากบรรทัดคำสั่งด้วย --enable-experimental-web-platform-features หรือ Flag --enable-features=FetchLaterAPI ที่มุ่งเน้นมากขึ้น

หากใช้ในหน้าสาธารณะ ให้ตรวจสอบว่ามีการกำหนด fetchLater ระดับส่วนกลางไว้หรือไม่ก่อนใช้งาน โดยทำดังนี้

if (globalThis.fetchLater) {
  // Set up beaconing using fetchLater().
  // ...
}

ความคิดเห็น

ความคิดเห็นของนักพัฒนาแอปเป็นสิ่งสำคัญที่จะทำให้ Web API ใหม่ทำงานได้อย่างถูกต้อง ดังนั้นโปรดแจ้งปัญหาและแสดงความคิดเห็นใน GitHub

ข้อมูลเพิ่มเติม