Sự kiện đẩy

Đến đây, chúng ta đã đề cập đến việc đăng ký người dùng và gửi thông báo đẩy. Bước tiếp theo là nhận thông báo đẩy này trên thiết bị của người dùng và hiển thị thông báo (cũng như thực hiện mọi công việc khác mà chúng ta có thể muốn làm).

Khi nhận được một thông báo, hệ thống sẽ gửi một sự kiện đẩy trong worker dịch vụ.

Mã để thiết lập trình nghe sự kiện đẩy sẽ khá giống với mọi trình nghe sự kiện khác mà bạn viết bằng JavaScript:

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.');
    }
});

Phần kỳ lạ nhất của mã này đối với hầu hết các nhà phát triển mới làm quen với worker dịch vụ là biến self. self thường được dùng trong Trình chạy web, một loại trình chạy dịch vụ. self đề cập đến phạm vi toàn cục, giống như window trong một trang web. Tuy nhiên, đối với trình chạy web và trình chạy dịch vụ, self đề cập đến chính trình chạy đó.

Trong ví dụ trên, bạn có thể coi self.addEventListener() là việc thêm trình nghe sự kiện vào chính worker dịch vụ.

Bên trong ví dụ về sự kiện đẩy, chúng ta kiểm tra xem có dữ liệu nào không và in nội dung nào đó vào bảng điều khiển.

Bạn có thể phân tích cú pháp dữ liệu từ một sự kiện đẩy theo các cách khác:

// 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()

Hầu hết mọi người đều sử dụng json() hoặc text() tuỳ thuộc vào những gì họ mong đợi từ ứng dụng của mình.

Ví dụ này minh hoạ cách thêm trình nghe sự kiện đẩy và cách truy cập dữ liệu, nhưng thiếu hai chức năng rất quan trọng. Không hiện thông báo và không dùng event.waitUntil().

Chờ đến

Một trong những điều cần hiểu về worker dịch vụ là bạn có ít quyền kiểm soát thời điểm mã worker dịch vụ sẽ chạy. Trình duyệt sẽ quyết định thời điểm đánh thức và thời điểm chấm dứt. Cách duy nhất để bạn có thể nói với trình duyệt rằng "Này, tôi đang rất bận làm những việc quan trọng" là truyền một lời hứa vào phương thức event.waitUntil(). Với thao tác này, trình duyệt sẽ duy trì chạy trình chạy dịch vụ cho đến khi thực hiện lời hứa mà bạn đã thực hiện.

Với các sự kiện đẩy, bạn phải hiển thị thông báo trước khi lời hứa mà bạn đã truyền vào được thực hiện.

Sau đây là ví dụ cơ bản về cách hiển thị thông báo:

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

    event.waitUntil(promiseChain);
});

Việc gọi self.registration.showNotification() là phương thức hiển thị thông báo cho người dùng và trả về một lời hứa sẽ giải quyết sau khi thông báo được hiển thị.

Để giữ cho ví dụ này rõ ràng nhất có thể, tôi đã gán lời hứa này cho một biến có tên là promiseChain. Sau đó, giá trị này được truyền vào event.waitUntil(). Tôi biết rằng nội dung này rất dài dòng, nhưng tôi đã thấy một số vấn đề phát sinh do hiểu sai về nội dung cần truyền vào waitUntil() hoặc do chuỗi lời hứa bị phá vỡ.

Một ví dụ phức tạp hơn với yêu cầu mạng về dữ liệu và theo dõi sự kiện đẩy bằng phân tích có thể có dạng như sau:

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);
});

Ở đây, chúng ta đang gọi một hàm trả về một lời hứa pushReceivedTracking(). Để minh hoạ, chúng ta có thể giả vờ rằng hàm này sẽ tạo một yêu cầu mạng đến nhà cung cấp dịch vụ phân tích. Chúng ta cũng đang tạo một yêu cầu mạng, nhận phản hồi và hiển thị thông báo bằng cách sử dụng dữ liệu phản hồi cho tiêu đề và thông báo của thông báo.

Chúng ta có thể đảm bảo rằng worker dịch vụ vẫn hoạt động trong khi cả hai tác vụ này được thực hiện bằng cách kết hợp các lời hứa này với Promise.all(). Lời hứa thu được được truyền vào event.waitUntil(), nghĩa là trình duyệt sẽ đợi cho đến khi cả hai lời hứa đều hoàn tất trước khi kiểm tra xem thông báo đã hiển thị hay chưa và chấm dứt worker dịch vụ.

Lý do chúng ta nên quan tâm đến waitUntil() và cách sử dụng là vì một trong những vấn đề phổ biến nhất mà nhà phát triển gặp phải là khi chuỗi hứa hẹn không chính xác/bị hỏng, Chrome sẽ hiển thị thông báo "mặc định" này:

Hình ảnh thông báo mặc định trong Chrome

Chrome sẽ chỉ hiển thị thông báo "Trang web này đã được cập nhật ở chế độ nền" khi nhận được thông báo đẩy và sự kiện đẩy trong worker dịch vụ không hiển thị thông báo sau khi lời hứa được chuyển đến event.waitUntil() đã kết thúc.

Nguyên nhân chính khiến nhà phát triển gặp phải vấn đề này là do mã của họ thường gọi self.registration.showNotification() nhưng không làm gì với lời hứa mà hàm này trả về. Điều này dẫn đến việc thông báo mặc định hiển thị không liên tục. Ví dụ: chúng ta có thể xoá lệnh trả về cho self.registration.showNotification() trong ví dụ trên và có nguy cơ thấy thông báo này.

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);
});

Bạn có thể thấy đây là một điều dễ bỏ qua.

Hãy nhớ rằng nếu bạn thấy thông báo đó, hãy kiểm tra các chuỗi hứa hẹn và event.waitUntil().

Trong phần tiếp theo, chúng ta sẽ xem xét những việc có thể làm để tạo kiểu cho thông báo và nội dung có thể hiển thị.

Bước tiếp theo

Lớp học lập trình