راه های مختلف نمایش notification در وبسایت ها و وب اپلیکیشن ها

راه های مختلف نمایش notification در وبسایت ها و وب اپلیکیشن ها

در قسمت اول از سری مقالات «آموزش ارسال notification در یک سایت»، می خواهیم با روش های مختلف ارسال اعلان(notification) از طریق مرورگر آشنا شویم.

 همان طور که می دانیم، بعنوان طراح و برنامه نویس یک وبسایت یا وب اپلیکیشن، بسیاری اوقات نیاز می شود که به کاربر اعلانی را نمایش بدهیم و او را از یک خبر و یا اتفاق  جدید در برنامه باخبر کنیم. بعنوان مثال، فرض کنید یک اپلیکیشن چت داریم که در آن می توانیم با دوستان خود پیام مبادله کنیم. بعنوان برنامه نویس این اپلیکیشن، می خواهیم هر بار که برای کاربر پیام جدیدی آمد، از طریق یک اعلان او را مطلع سازیم. یا فرض کنید یک سایت فروش بلیط هواپیما داریم، و می خواهیم بعد از اینکه کاربری از ما بلیط خرید، چنانچه پروازش تأخیر داشت به وی اطلاع دهیم و ... .

منطق کلی بدین ترتیب است که در برنامه ی ما یا سمت سرور اتفاقی می افتد (مثل «خرید موفق یک بلیط» یا «به تأخیر افتادن یک پرواز»)، و ما به ازای آن اعلانی را ارسال می کنیم تا کاربران را مطلع کنیم. (این «اتفاق» با عبارت فنی event شناخته می شود)

هم چنین از اعلان ها برای مقاصد تبلیغاتی زیادی استفاده می شود. در مجموع می توان گفت اعلان ها به ما کمک می کنند که در کاربران وبسایتمان انگیزه ایجاد کنیم، تا مجدداً به سایت ما سر بزنند. پیاده سازی سمت سرور اعلان ها، و اینکه با چه ابزار هایی می توان آنها را برای کاربران ارسال کرد، اکنون مورد بحث ما نیست. که البته آن نیز چندان پیچیده نیست و بسته به نیاز برنامه نویس، و یا تکنولوژی ای که در سمت سرور استفاده می کند، راه های مختلفی برای پیاده سازی اش وجود دارد. هر چند در ادامه ی مباحث به این موضوع خواهیم پرداخت، در اینجا فرض بر آن است که ما اتفاق(event) های سرور را در سمت کلاینت(client side) به درستی دریافت می کنیم، و حال روی این بحث می کنیم که چطور اعلان مربوط به آن اتفاق را به کاربر نشان دهیم.

بطور کلی از طریق مرورگر، می توان در سه سطح برای کاربر اعلان نمایش داد:

اعلان های درون برنامه ای:

در واقع این نوع اعلان ها نام خاصی ندارند و ما خود نام «اعلان درون برنامه ای» را روی آن گذاشته ایم. این ها آن دسته اعلان هایی هستند که در خود برنامه، و بصورت دستی ایجاد می شوند. یعنی ما به دلخواه خود، بلوکی به DOM صفحه اضافه می کنیم و با آن اعلان نمایش می دهیم. منظور از DOM یاDocument Object Model، همان ساختار درختی مربوط به المان هاییست که در صفحه نمایش داده می شوند. بعنوان مثال وقتی کاربر سایت ما با موفقیت وارد برنامه شد، با یک نوار سبز به او خوش آمد می گوییم. یا وقتی در یک سایت رصد نتایج زنده ی مسابقات ورزشی، در حین انجام مسابقه گلی به ثمر رسید، با یک پیام کوچک کاربر را از این اتفاق جدید آگاه می کنیم. در مجموع بسته به نیاز برنامه و با توجه به تجربه کاربری سایت، می توانیم از روش ها و طرح های مختلفی برای نمایش اعلان های درون برنامه ای استفاده کنیم. بعنوان مثال با یک پیام popup این کار را انجام دهیم یا با یک flash message یا toast message این اتفاق را به نظر کاربر برسانیم. برای نمایش چنین پیام هایی کتابخانه های متعددی ایجاد شده اند که کار برنامه نویس رابط کاربری را خیلی ساده می کنند. اگر وبسایت خود را با فریم ورک خاصی نوشته اید(مثلاً angular، vue، react و ...)، حتماً با یک جستجوی ساده می توانید کتابخانه های سازگار با فریم ورکتان را برای این منظور پیدا کنید. برای مثال وقتی در bookmark manager کروم یکی از بوک مارک هایمان را حذف می کنیم، یک toast notification به ما نمایش داده می شود. به تصویر زیر دقت کنید:

اگر در این لحظه از صفحه inspect بگیریم (مثلاً DOM صفحه را با رفتن به ابزار توسعه ی مرورگر و با فشردن ctrl + shift + I مشاهده کنیم)، می بینیم که یک تگ جدید به DOM اضافه شده. یعنی این اعلان ها زیرمجموعه viewport تعریف می شوند. این نوع اعلان ها، از آن جایی که عضوی از DOM هستند، خیلی دستمان را برای سفارشی سازی(customization) باز می گذارند. می توانیم آن ها را هر جایی از صفحه که خواستیم قرار دهیم، میتوانیم اسکریپت های مختلف را به ازای تعامل کاربر با آنها اجرا کنیم، در آنها دکمه های مختلف بگذاریم و هر منطقی که خواستیم را به آن ها تزریق کنیم. چرا که واقعاً بخشی از صفحه ی ما هستند. اما کاربر تنها موقعی می تواند این اعلان ها را ببیند، که اولاً مرورگرش باز باشد و بالا باشد(در حالت minimize نباشد)، و ثانیاً تب مربوط به اپلیکیشن ما را باز کرده باشد، و ثالثاً مشغول مشاهده ی تب مربوط به اپلیکیشن ما باشد (در حال مشاهده ی یک سایت دیگر نباشد یا به اصطلاح تب مربوطه فعال یا active باشد).

سوالی که در اینجا پیش می آید، آن است که اگر کاربر درون آن تب نبود، آیا می توانست اعلانی را که ما برای او نمایش داده ایم ببیند؟ یا اگر کاربر مرورگر خود را باز کرده بود، ولی بعد به تب دیگری رفته بود؟ یا اگر کاربر اپلیکیشن ما را در مرورگرش باز کرده بود، اما بعد از آن مرورگرش را minimize کرده بود و در صفحه ی دسکتاپش بود؟ طبیعی ست که در این موارد کاربر نمی تواند اعلان هایی که به او نمایش می دهیم را ببیند. اینجاست که باید به سراغ لایه دوم نمایش اعلان برویم.

نمایش اعلان با استفاده از Notification API:

لایه بعدی نمایش اعلان، استفاده از Notification API است. این API که زیرمجموعه ی Web API ها محسوب می شود، کاری می کند که بتوانیم در سطح سیستم(system level) اعلان نمایش دهیم. با استفاده از این API میتوانیم در سیستم عامل، یک system notification ایجاد کنیم. به عبارت دیگر اعلانی که از این طریق ایجاد می کنیم، خارج از صفحه (بیرون از viewport) و در سطح سیستم عامل (OS) است. برای همین اگر اپلیکیشنمان در حالت idle باشد، یا اینکه در background کار کند، باز هم می تواند این اعلان ها را به کاربر نشان دهد. و این همان مشکلی بود که اعلان های درون برنامه ای قادر به حل آن نبودند!

موقع کار با Notification API قبل از هر چیز باید چک کنیم که مرورگر کاربر از این قابلیت پشتیبانی می کند یا نه. دوم اینکه برای نمایش اعلان از طریق Notification API، باید کاربر به برنامه اجازه داده باشد. این مورد و مورد قبل، و همچنین اینکه بهترین روش اجازه گرفتن از کاربر از نظر تجربه کاربری چیست، و برخی نکات کوچک دیگر را در ادامه ی سری مقالات پی خواهیم گرفت.

می دانیم که جاوااسکریپت یک زبان تک نخی (single threaded) است. در دنیای صفحات وب، منظورمان از main thread یعنی همان نخ اصلی جاوااسکریپتی که مدیریت صفحه و DOM و تعامل با کاربر را در اختیار دارد، به window دسترسی دارد و ... .

نکته این جاست که اگر از Notification API در نخ اصلیِ برنامه(main thread) استفاده کنیم، یعنی کد آن را در اسکریپت های عادی برنامه اضافه کنیم، باز با محدودیت هایی مواجه می شویم. می دانیم Notification API چیزی نیست جز یک سری کد (تابع و آبجکت و ... )، که ما از طریقشان اعلان ایجاد می کنیم. در واقع کد هایی که در نخ اصلی قرار دارند، برای کار کردن نیاز به باز بودن تبِ مربوطه دارند. از این منظر می توان گفت که Notification API با اعلان های درون برنامه ای تفاوتی ندارد و تنها مزیتش این است که نیازی به حضور ما در تب سایت نیست(active بودن تب سایت ضروری نیست)، اما همچنان باز بودن تب سایت ضروری ست. در واقع اعلانی که Notification API قرار است نمایش دهد، خارج از DOM و در سطح سیستم عامل است، به همین دلیل برای دیدن این اعلان نیاز نیست که حتماً تبِ باز شده active هم باشد.

با این توضیحات حتماً دریافته اید که Notification API به تنهایی پاسخگوی برخی نیاز های ما نیست. فرض کنید کاربر یک سایت فروشگاهی، می خواهد وبسایت هر وقت که یک جنس خاص در انبارش موجود شد، به او اطلاع بدهد، حال آنکه این اتفاق(موجود شدن کالا در انبار) ممکن است امروز بیفتد، ممکن است فردا بیفتد، و ممکن است هیچوقت رخ ندهد! به همین دلیل کاربر نمی تواند همیشه در مرورگر خود، تب وبسایت را باز نگه دارد، به این امید که آن کالا موجود شود و اعلانش را ببیند!!

و این جاست که یک سوال دیگر پیش می آید، اگر بخواهیم حتی وقتی تبمان باز نیست هم اعلان نمایش بدهیم، چه باید بکنیم؟ حتماً شما نیز بسیاری از سایت ها را دیده اید که چنین قابلیتی دارند. مثلاً سایت های دانلود محتوا یک بار از شما اجازه می گیرند که هر وقت محتوای جدیدی آماده شد، برای شما اعلان بفرستند. اگر آن درخواست را قبول کنید، از این به بعد حتی اگر سایتشان را هم باز نکرده باشید، اعلان های آن برای شما فرستاده می شود. نمونه ی دیگرش را شاید در سایت های فروشگاهی دیده باشید و ... .

اما این اعلان ها چطور پیاده سازی می شوند؟ با استفاده از service worker ها!

پس به سراغ معرفی سطح سوم نمایش اعلان می رویم، و آن چیزی نیست جز: «استفاده از اعلان سیستم عاملی در service worker ها»

ارسال web push notification (نمایش اعلان با استفاده از service worker ها):

قبل از اینکه شروع کنیم، خوب است که اشاره ی کوچکی به مبحث worker ها داشته باشیم. web worker ها که در این مقاله اختصاراً به آن ها worker می گوییم، یک سری script (یک فایل .js مجزا) هستند که مرورگر آن ها را در نخ های جداگانه ای، در پس زمینه اجرا می کند. گفتیم که ما در هر تب از مرورگر، یک نخ اصلی داریم که جاوااسکریپت اصلی صفحه است، یعنی همان اسکریپتی که کنترل DOM صفحه و در کل interface را بر عهده دارد. مثلاً وقتی که روی یک دکمه کلیک می کنیم، این جاوااسکریپت نخ اصلی است که کلیک کردن ما را مدیریت می کند و به آن پاسخ می دهد. حالا worker ها مجموعه ای از اسکریپت ها هستند، که بصورت موازی با نخ اصلی و در نخ مخصوص به خودشان اجرا می شوند (run می شوند)، به المان های صفحه دسترسی مستقیم ندارند و اگر بخواهند با ترد اصلی ارتباط برقرار کنند، باید با استفاده از api مخصوص این کار را انجام دهند(مثلاً با متد postMessage برای نخ اصلی پیام بفرستند).

 از آنجایی که این ترد ها با ترد اصلی فرق دارند، عملاً یک تجربه ی multithreading (چندنخی) را به مرورگر ها اضافه می کنند، کارشان باعث اختلال در کار ترد اصلی نمی شود، می توانند محاسبات سنگین را در پس زمینه بر عهده بگیرند و بسیاری کار های دیگر. این worker ها انواع مختلفی دارند که هر کدام از آنها برای کار خاصی مناسب هستند.

حالا service worker چیست؟ نوعی خاص از worker ها!

در قسمت های بعد، برای service worker یک مقاله ی جداگانه در نظر گرفته ایم و از این رو قصد نداریم در این مقاله وارد مباحث عمیق آن بشویم یا با هم کد ببینیم. اما ویژگی قابل توجه service worker این است که حتی اگر تب مرورگر باز نباشد، توسط مرورگر اجرا می شود و این همان مشکلی بود که در دو روش قبلی قادر به حل آن نبودیم.

خوب است بدانیم که service worker کاربرد های زیادی دارد، و ارسال push notification تنها یکی از کارکرد های آن است. و اما روال کلی ارسال push notification از طریق service worker بدین ترتیب است:

  • اول نیاز داریم سمت کاربر یک service worker ایجاد کنیم، و به مرورگر بگوییم که به ازای یک سایت خاص(یا بطور دقیق تر به ازای یک origin خاص)، این service worker را در پس زمینه اجرا کند. برای این کار ابتدا باید service worker خود را register کنیم. اگر همه چیز خوب پیش برود، کد service worker توسط مرورگر دانلود می شود، parse می شود، سپس با اطمینان یافتن از اینکه فاقد ارور است، install می شود و active می شود و وقتی که active شد، اصطلاحاً میگویند کنترل صفحه را به دست گرفته. کد داخلی سرویس ورکر، که در آینده مفصل به آن خواهیم پرداخت، پر از eventListener هاست. و اساس کار service worker این است که به ازای حالات و اتفاق های مختلف، یک سری callback در نظر می گیرد و هر وقت آن حالت یا اتفاق رخ داد، callback مربوطه را اجرا می کند. یکی از این اتفاق ها، اتفاق 'push' است. در کد service worker، روی push event یک callback می گذاریم و به آن می گوییم که هرگاه یک اتفاق push روی داد، یک اعلان نمایش بده (قسمت service worker و کلاینت). حال اگر این اعلان را با چیزی شبیه Notification API نمایش دهیم، کاربر در سطح سیستم عامل آن را دریافت خواهد کرد و دیگر حتی نیاز به بالا بودن تب مربوط به وبسایت نیز وجود ندارد. این روش همان روشی ست که در بسیاری از سایت های امروزی مورد استفاده قرار می گیرد و احتمالاً خودتان به عنوان کاربر آن را تجربه کرده اید. به این ترتیب ما با استفاده از service worker نیاز به باز بودن سایت را از بین بردیم و با استفاده از نمایش اعلان در سطح سیستم عامل، نیاز به بالا بودن مرورگر را از بین بردیم.
  • از طرفی در سمت سرور نیاز داریم که اولاً زمان ارسال push notification را تعیین کنیم (بعنوان مثال اینکه چه زمانی یک کالا در انبار موجود می شود را باید سرور تشخیص دهد و تعیین کند)، و هم اینکه محتوای push notification را تعیین کنیم. (بخش سرور)
  • از طرف دیگر وقتی سرور تعیین کرد که چه push notification ای و در چه زمانی باید ارسال شود، آن را با کمک یک سرویس سوم که به آن push service گفته می شود برای کاربر ارسال می کند. بدین ترتیب سرور با push service هماهنگی های لازم را انجام می دهند و اعلان با موفقیت ارسال می شود. با دریافت این اعلان از طریق service worker و نمایش آن در سطح سیستم عامل، یک چرخه ی نمایش push notification تکمیل می شود.

در قسمت بعد از سری مقالات «آموزش ارسال Notification در یک سایت»، به بحث Notification API بیشتر می پردازیم و با هم کد های مربوط به آن را خواهیم دید.

نظرات
اگر login نکردی برامون ایمیلت رو بنویس: