رویدادهای Push

تا اینجا، مشترک کردن کاربر و ارسال پیام لحظه‌ای را پوشش دادیم. مرحله بعدی این است که این پیام لحظه‌ای را در دستگاه کاربر دریافت کنیم و اعلانی را نمایش دهیم (و همچنین هر کار دیگری را که ممکن است بخواهیم انجام دهیم).

رویداد ارسال

وقتی پیامی دریافت می‌شود، منجر به ارسال رویداد لحظه‌ای در کارگر سرویس شما می‌شود.

کد راه‌اندازی شنونده رویداد فشاری باید بسیار شبیه به هر شنونده رویداد دیگری باشد که در جاوا اسکریپت می‌نویسید:

self.addEventListener('push', function(event) {
    if (event.data) {
    console.log('This push event has data: ', event.data.text());
    } else {
    console.log('This push event has no data.');
    }
});

عجیب‌ترین بخش این کد برای اکثر توسعه‌دهندگانی که با کارگران خدمات آشنا نیستند، متغیر self است. ‫self معمولاً در Web Workers استفاده می‌شود که سرویس‌کار هم یکی از آن‌ها است. self به دامنه سراسری اشاره دارد، چیزی شبیه به window در صفحه وب. اما برای وب‌ورکرها و سرویس‌ورکرها، self به خود ورکر اشاره دارد.

در مثال بالا، self.addEventListener() را می‌توان به‌عنوان افزودن شنونده رویداد به خود سرویس‌کار درنظر گرفت.

در مثال رویداد push، بررسی می‌کنیم که آیا داده‌ای وجود دارد یا نه و چیزی را در کنسول چاپ می‌کنیم.

روش‌های دیگری برای تجزیه کردن داده‌ها از رویداد لحظه‌ای وجود دارد:

// Returns string
event.data.text()

// Parses data as JSON string and returns an Object
event.data.json()

// Returns blob of data
event.data.blob()

// Returns an arrayBuffer
event.data.arrayBuffer()

اکثر افراد بسته به انتظاری که از برنامه خود دارند، از json() یا text() استفاده می‌کنند.

این مثال نشان می‌دهد که چگونه یک شنونده رویداد push اضافه کنید و چگونه به داده‌ها دسترسی پیدا کنید، اما دو بخش بسیار مهم از عملکرد را ندارد. اعلان نشان نمی‌دهد و از event.waitUntil() استفاده نمی‌کند.

صبر کردن تا

یکی از چیزهایی که باید درباره سرویس‌کارها بدانید این است که کنترل کمی بر زمان اجرای کد سرویس‌کار دارید. مرورگر تصمیم می‌گیرد که چه زمانی آن را فعال کند و چه زمانی آن را خاتمه دهد. تنها راهی که می‌توانید به مرورگر بگویید «هی، من خیلی مشغول انجام کارهای مهم هستم» این است که یک promise را به روش event.waitUntil() ارسال کنید. با این کار، مرورگر عامل خدماتی را تا زمانی که وعده ارسال‌شده شما حل‌وفصل شود، فعال نگه می‌دارد.

با رویدادهای push، یک الزام اضافی وجود دارد که باید قبل‌از اینکه promise که ارسال کرده‌اید حل شود، یک اعلان نمایش دهید.

در اینجا نمونه‌ای ساده از نمایش اعلان آورده شده است:

self.addEventListener('push', function(event) {
    const promiseChain = self.registration.showNotification('Hello, World.');

    event.waitUntil(promiseChain);
});

فراخوانی self.registration.showNotification() روشی است که اعلانی را به کاربر نمایش می‌دهد و قولی را برمی‌گرداند که پس‌از نمایش اعلان حل خواهد شد.

برای اینکه این مثال تا حد امکان واضح باشد، این وعده را به متغیری به‌نام promiseChain اختصاص داده‌ام. سپس این به event.waitUntil() منتقل می‌شود. I know this is very verbose, but I've seen a number of issues that have culminated as a result of misunderstanding what should be passed into waitUntil() or as a result of broken promise chains.

نمونه پیچیده‌تری با درخواست شبکه برای داده و ردیابی رویداد push با analytics می‌تواند به‌صورت زیر باشد:

self.addEventListener('push', function(event) {
    const analyticsPromise = pushReceivedTracking();
    const pushInfoPromise = fetch('/api/get-more-data')
    .then(function(response) {
        return response.json();
    })
    .then(function(response) {
        const title = response.data.userName + ' says...';
        const message = response.data.message;

        return self.registration.showNotification(title, {
        body: message
        });
    });

    const promiseChain = Promise.all([
    analyticsPromise,
    pushInfoPromise
    ]);

    event.waitUntil(promiseChain);
});

در اینجا تابعی را فراخوانی می‌کنیم که یک promise pushReceivedTracking() را برمی‌گرداند، که برای این مثال، می‌توانیم فرض کنیم که یک درخواست شبکه به ارائه‌دهنده تجزیه‌وتحلیل ما ارسال می‌کند. همچنین درخواست شبکه ایجاد می‌کنیم، پاسخ را دریافت می‌کنیم، و بااستفاده از داده‌های پاسخ، اعلانی برای عنوان و پیام اعلان نشان می‌دهیم.

با ترکیب کردن این وعده‌ها با Promise.all() می‌توانیم مطمئن شویم که کارگر سرویس درحین انجام هر دو این کارها فعال نگه داشته می‌شود. قول حاصل به event.waitUntil() منتقل می‌شود، یعنی مرورگر منتظر می‌ماند تا هر دو قول تکمیل شوند و سپس بررسی می‌کند که اعلان نمایش داده شده باشد و کارگر سرویس را خاتمه می‌دهد.

دلیل اینکه باید نگران waitUntil() و نحوه استفاده از آن باشیم این است که یکی از رایج‌ترین مشکلاتی که توسعه‌دهندگان با آن مواجه می‌شوند این است که وقتی زنجیره وعده نادرست / شکسته است، Chrome این اعلان «پیش‌فرض» را نشان می‌دهد:

تصویری از اعلان پیش‌فرض در Chrome

‫Chrome فقط زمانی اعلان «این سایت در پس‌زمینه به‌روزرسانی شده است» را نشان می‌دهد که پیام لحظه‌ای دریافت شود و رویداد لحظه‌ای در کارگر سرویس پس‌از پایان وعده ارسال‌شده به event.waitUntil()، اعلانی نشان ندهد.

دلیل اصلی اینکه توسعه‌دهندگان در این تله می‌افتند این است که کد آن‌ها اغلب self.registration.showNotification() را فراخوانی می‌کند اما آن‌ها با وعده‌ای که برمی‌گرداند کاری انجام نمی‌دهند. این امر گاه‌به‌گاه باعث می‌شود اعلان پیش‌فرض نمایش داده شود. برای مثال، می‌توانیم مقدار برگشتی برای self.registration.showNotification() را در مثال بالا برداریم و با خطر دیدن این اعلان مواجه شویم.

self.addEventListener('push', function(event) {
    const analyticsPromise = pushReceivedTracking();
    const pushInfoPromise = fetch('/api/get-more-data')
    .then(function(response) {
        return response.json();
    })
    .then(function(response) {
        const title = response.data.userName + ' says...';
        const message = response.data.message;

        self.registration.showNotification(title, {
        body: message
        });
    });

    const promiseChain = Promise.all([
    analyticsPromise,
    pushInfoPromise
    ]);

    event.waitUntil(promiseChain);
});

می‌توانید ببینید که چطور ممکن است به‌راحتی از دست برود.

فقط یادتان باشد - اگر آن اعلان را دیدید، زنجیره‌های promise و event.waitUntil() را بررسی کنید.

در بخش بعدی، می‌خواهیم ببینیم چه کارهایی می‌توانیم برای سبک‌دهی به اعلان‌ها انجام دهیم و چه محتوایی را می‌توانیم نمایش دهیم.

مقصد بعدی کجاست

Code labs