مقدمه
یک نیاز بسیار رایج در تحلیل وب (analytics)، ارسال اطلاعاتی درباره جلسه کاری کاربر به سرور، درست
در لحظهای است که کاربر قصد خروج از صفحه را دارد (مثلاً با بستن تب یا کلیک روی یک لینک خارجی).
این اطلاعات میتواند شامل مدت زمان حضور در صفحه، آخرین عملیات انجام شده، یا دادههای یک فرم
ناتمام باشد.
انجام این کار به طور قابل اعتماد، یک چالش تاریخی در توسعه وب بوده است. استفاده از یک درخواست
fetch یا XHR معمولی در شنونده رویداد unload یا beforeunload قابل
اطمینان نیست، زیرا مرورگر هیچ تضمینی نمیدهد که این درخواستهای ناهمزمان قبل از بسته شدن کامل
صفحه، به سرور برسند. مرورگر برای سرعت بخشیدن به ناوبری کاربر، ممکن است هرگونه درخواست در حال
انتظار را لغو کند.
راهحل: Beacon API
Beacon API به طور خاص برای حل این مشکل طراحی شده است. این API یک روش استاندارد برای ارسال
حجم کوچکی از دادهها از مرورگر به سرور، به صورت ناهمزمان و بدون انتظار برای دریافت پاسخ، فراهم
میکند. مرورگر تضمین میکند که درخواست beacon را در اولین فرصت مناسب ارسال کرده و این فرآیند،
ناوبری کاربر به صفحه بعدی را مسدود یا کند نخواهد کرد.
ویژگیهای کلیدی Beacon API
- غیر مسدود کننده (Non-blocking): درخواست در پسزمینه به صف ارسال اضافه میشود و اجرای
اسکریپت شما را متوقف نمیکند.
- قابل اعتماد: مرورگر ارسال آن را تضمین میکند، حتی اگر صفحه در حال بسته شدن باشد.
- بهینه: مرورگر میتواند برای ارسال beacon، منتظر یک زمان مناسب (مانند زمانی که شبکه
آزاد است) بماند تا عملکرد کلی را بهبود بخشد.
- یکطرفه: این یک مکانیزم "شلیک کن و فراموش کن" (fire-and-forget) است. شما داده را
ارسال میکنید، اما هیچ پاسخی از سرور در کد خود دریافت نخواهید کرد.
سینتکس و کاربرد
استفاده از این API به طرز شگفتآوری ساده است و تنها شامل یک متد است: navigator.sendBeacon(url, data).
- url: آدرس URL اندپوینتی روی سرور شما که برای دریافت این دادهها طراحی شده است.
- data: دادهای که میخواهید ارسال کنید. این داده میتواند یک Blob، FormData،
URLSearchParams یا ArrayBufferView باشد.
متد sendBeacon() یک مقدار بولی برمیگرداند. مقدار true به
این معنی است که مرورگر با موفقیت داده را برای ارسال در صف قرار داده است. مقدار false
معمولاً به این معنی است که حجم داده ارسالی بیش از حد مجاز بوده است. توجه داشته باشید که
true بودن این مقدار، تحویل موفقیتآمیز به سرور را تضمین نمیکند، بلکه تنها موفقیت در
صفبندی را نشان میدهد.
JAVASCRIPT
function logAnalytics() {
const analyticsData = {
timeSpent: Math.round(performance.now()),
lastAction: 'read-article',
screenWidth: window.innerWidth
};
const blob = new Blob([JSON.stringify(analyticsData)], {
type: 'application/json'
});
navigator.sendBeacon('/log-analytics', blob);
}
در این مثال، یک شیء حاوی اطلاعات آماری را به یک رشته JSON تبدیل کرده و سپس آن را در یک شیء
Blob با نوع محتوای صحیح قرار میدهیم. در نهایت، این Blob را با sendBeacon() به سرور ارسال میکنیم.
یک رویداد بهتر برای خروج: visibilitychange
رویداد unload به طور فزایندهای در مرورگرهای مدرن غیرقابل اعتماد تلقی میشود و استفاده از
آن توصیه نمیشود. یک جایگزین بسیار بهتر و قابل اعتمادتر، رویداد visibilitychange است. این
رویداد هر زمان که وضعیت دیدهشدن یک تب تغییر میکند (مثلاً کاربر به تب دیگری میرود یا پنجره را
minimize میکند) اجرا میشود.
ما میتوانیم به این رویداد گوش دهیم و زمانی که پراپرتی document.visibilityState برابر با
'hidden' میشود، beacon خود را ارسال کنیم. این آخرین لحظهی قابل اعتمادی است که میتوانیم
قبل از اینکه کاربر به طور بالقوه تب را ببندد، کد خود را اجرا کنیم.
JAVASCRIPT
document.addEventListener('visibilitychange', () => {
if (document.visibilityState === 'hidden') {
const data = new FormData();
data.append('event', 'user-left-page');
data.append('timestamp', Date.now());
navigator.sendBeacon('/log-events', data);
}
});
این الگو بسیار قویتر از استفاده از رویداد unload است و تضمین میکند که دادههای تحلیلی
شما با اطمینان بیشتری ارسال میشوند.
در این درس با Beacon API به عنوان روشی مطمئن و بهینه برای ارسال حجم کوچکی از دادهها به
سرور، به خصوص در هنگام خروج کاربر از صفحه، آشنا شدیم. این API یک ابزار تخصصی اما بسیار کارآمد
برای سناریوهایی مانند ثبت آمار و لاگها است. در درس بعدی، به سراغ Web Sockets خواهیم رفت،
یک تکنولوژی قدرتمند که امکان ارتباط دوطرفه و زنده بین کلاینت و سرور را فراهم میکند.