تشخیص وضعیت رؤیت‌پذیری اولیه

تشخیص اینکه آیا صفحه‌ای در ابتدا در پس‌زمینه بار شده است (مثلاً در زبانه پس‌زمینه جدیدی باز شده است) برای پایش دقیق عملکرد بسیار مهم است. صفحه‌های بارشده در پس‌زمینه اغلب پردازش با تأخیر و زمان سنجه طولانی‌تری دارند (مثل «اولین رنگ‌آمیزی محتوایی»). شناسایی این صفحه‌ها به شما امکان می‌دهد آن‌ها را از تجزیه‌وتحلیل عملکرد فیلتر کنید تا از داده‌های انحرافی جلوگیری شود.

دقیق‌ترین روش برای اندازه‌گیری این مورد استفاده از VisibilityStateEntry API است که تغییرات رؤیت‌پذیری را به‌طور قابل‌اعتماد در خط زمان عملکرد مرورگر ثبت می‌کند، صرف‌نظر از اینکه اسکریپت شما واقعاً چه زمانی اجرا می‌شود.

درحال تشخیص رؤیت‌پذیری اولیه و زمان پس‌زمینه

اجباری: برای دسترسی به سابقه رؤیت‌پذیری دقیق، از performance.getEntriesByType('visibility-state') استفاده کنید. فقط به بررسی document.visibilityState در زمان اجرا تکیه نکنید، زیرا مستعد شرایط رقابتی است.

/**
 * Accurately determines visibility state history using the Performance API.
 */
function getVisibilityInfo() {
  // Retrieve VisibilityStateEntry members:
  const entries = performance.getEntriesByType('visibility-state');
  
  if (entries.length > 0) {
    const firstEntry = entries[0];
    
    // If the first performance entry for visibility is 'hidden',
    // the page was loaded in the background.
    const initiallyBackgrounded = firstEntry.name === 'hidden';
    
    // Find the precise, high-resolution timestamp of when the page 
    // was first backgrounded.
    let timeBackgrounded = null;
    for (const entry of entries) {
      if (entry.name === 'hidden') {
        // entry.startTime is used because it provides the exact browser 
        // timestamp of the visibility change, which is required for precision
        timeBackgrounded = entry.startTime;
        break;
      }
    }

    return {
      initiallyBackgrounded,
      timeBackgrounded
    };
  }
}

راهبردهای جایگزین

برای محیط‌های پشتیبانی‌نشده، می‌توانید به بررسی ویژگی document.visibilityState یا گوش دادن به رویداد visibilitychange برگردید.

اجباری: باید بدانید که این رویکرد جایگزین اغلب برای تعیین وضعیت پس‌زمینه اولیه بسیار نادرست است. چون اسکریپت‌ها می‌توانند به‌صورت ناهمگام بارگیری و اجرا شوند، ممکن است صفحه‌ای در برگه پس‌زمینه باز شود و سپس توسط کاربر قبل‌از اینکه بارگیری و اجرای اسکریپت شما تمام شود به پیش‌زمینه آورده شود. وقتی درنهایت اسکریپت شما اجرا می‌شود، document.visibilityState به‌طور هم‌زمان به‌عنوان 'visible' خوانده می‌شود و شما به‌اشتباه فرض می‌کنید که صفحه در پیش‌زمینه بار شده است و حالت پنهان اولیه آن را کاملاً ازدست می‌دهید. علاوه‌براین، مُهر زمان بازگشت فاقد دقت داخلی Performance API است. اگر دقت اولویت بالایی دارد، از گزینه جایگزین استفاده نکنید.

/**
 * Fallback implementation using document.visibilityState.
 * This approach is prone to race conditions if the script loads asynchronously.
 */
function getFallbackVisibilityInfo() {
  // Check the state exactly when this script executes.
  // This will fail to detect an initial background state if the user 
  // foregrounded the page before this script executed.
  let initiallyBackgrounded = document.visibilityState === 'hidden';
  
  // If it's hidden now, we approximate that it was hidden from load (time 0).
  let timeBackgrounded = initiallyBackgrounded ? 0 : null;

  // Listen for future visibility changes to capture if it is backgrounded later.
  document.addEventListener('visibilitychange', () => {
    if (document.visibilityState === 'hidden' && timeBackgrounded === null) {
      // performance.now() is used here as a fallback, but it only gives 
      // us the time the event listener fired, not the precise internal 
      // browser time the visibility actually changed.
      timeBackgrounded = performance.now();
    }
  });

  return {
    get initiallyBackgrounded() { return initiallyBackgrounded; },
    get timeBackgrounded() { return timeBackgrounded; }
  };
}

// Modern implementation using VisibilityStateEntry API.
function getVisibilityInfo() {
  // Code omitted here would be the same modern
  // implementation shown earlier in this guide
  // ...
}

// DO: Detect if the VisibilityStateEntry API is available
if ('VisibilityStateEntry' in window) {
  // DO: If VisibilityStateEntry is available, use it first:
  getVisibilityInfo();
} else {
  // DO: If VisibilityStateEntry is unavailable, fall back to `document.visibilityState`:
  getFallbackVisibilityInfo();
}