Service Worker'larla iki yönlü iletişim

Andrew Guan
Andrew Guan
Demián Renzulli
Demián Renzulli

Bazı durumlarda, bir web uygulamasının hizmet çalışanıdır.

Örneğin, bir podcast PWA'sında kullanıcının ilgili bölümleri indirmesini sağlayacak bir özellik oluşturulabilir. çevrimdışı tüketim ve sayfayı ilerleme hakkında düzenli olarak bilgilendirmesini, böylece ana sayfa iş parçacığı, kullanıcı arayüzünü güncelleyebilir.

Bu kılavuzda Google Analytics 4'te Google ile iki yönlü bir iletişim kurmanın Pencere ve hizmet çalışan bağlamını inceleyelim. çeşitli API'ler, Workbox kitaplığı ve bazı ileri düzey durumlardan bahsetmek istiyorum.

Bir hizmet çalışanını ve mesaj alışverişinde bulunan sayfayı gösteren şema.

Workbox'ı kullanma

workbox-window, Workbox kitaplığının amaçlarına uygun modülleri çalıştırılması gerektiğini unutmayın. Workbox sınıfı, örneğin kayıtlı hizmet çalışanına mesaj göndermek için bir messageSW() yöntemi sağlar ve yanıt bekleyin.

Aşağıdaki sayfa kodu yeni bir Workbox örneği oluşturur ve hizmet çalışanına bir mesaj gönderir sürümünü edinmek için:

const wb = new Workbox('/sw.js');
wb.register();

const swVersion = await wb.messageSW({type: 'GET_VERSION'});
console.log('Service Worker version:', swVersion);

Service Worker, diğer tarafta bir mesaj işleyici uygular ve mesaja yanıt vermek için hizmet çalışanı:

const SW_VERSION = '1.0.0';

self.addEventListener('message', (event) => {
  if (event.data.type === 'GET_VERSION') {
    event.ports[0].postMessage(SW_VERSION);
  }
});

Temel olarak kitaplık bir tarayıcı API'si kullanır. Bu API'yi sonraki bölümde inceleyeceğiz: Kanal ancak birçok soyut bilgiler ayrıntılı bilgiler vererek daha kolay kullanılabilmesi için, genişletilmiş tarayıcı desteği hakkında daha fazla bilgi edinin.

Çalışma Kutusu Penceresi kullanarak sayfa ve hizmet çalışanı arasındaki iki yönlü iletişimi gösteren şema.

Tarayıcı API'lerini Kullanma

Workbox kitaplığınız ihtiyaçlarınız için yeterli değilse kullanabileceğiniz alt düzey API'ler vardır. sayfalar ve hizmet çalışanları arasında "iki yönlü" iletişim uygular. Bazı benzerlikleri vardır ve farklar:

Benzerlikler:

  • Her durumda, iletişim postMessage() arayüzü üzerinden bir tarafta başlar ve diğer tarafta message işleyici uygulayarak yapabilirsiniz.
  • Pratikte mevcut tüm API'ler, aynı kullanım alanlarını uygulamamıza olanak tanıyor ancak bazıları bazı senaryolarda geliştirmeyi kolaylaştırabilir.

Farklar:

  • İletişimin diğer tarafını tanımlamanın farklı yolları vardır. Bazıları başka bağlama açık referans verirken diğerleri bir proxy aracılığıyla üstü kapalı iletişim kurabilir oluşturulan bir nesnedir.
  • Tarayıcı desteği bunlardan birine göre değişir.
Sayfa ve hizmet çalışanı ile kullanılabilir tarayıcı API'leri arasındaki iki yönlü iletişimi gösteren şema.

Yayın Kanalı API'si

Tarayıcı Desteği

  • Chrome: 54.
  • Kenar: 79.
  • Firefox: 38.
  • Safari: 15.4

Kaynak

Yayın Kanalı API'si göz atma bağlamları arasında BroadcastChannel üzerinden temel iletişime olanak tanır nesnelerin yer aldığından emin olun.

Uygulamak için öncelikle her bağlamın aynı kimliğe sahip bir BroadcastChannel nesnesini örneklendirmesi gerekir ve buradan ileti gönderip alabilirsiniz:

const broadcast = new BroadcastChannel('channel-123');

BroadcastChannel nesnesi, herhangi bir dinleme deneyimine mesaj göndermek için bir postMessage() arayüzünü gösterir bağlam:

//send message
broadcast.postMessage({ type: 'MSG_ID', });

Herhangi bir tarayıcı bağlamı, BroadcastChannel öğesinin onmessage yöntemini kullanarak mesajları dinleyebilir nesne:

//listen to messages
broadcast.onmessage = (event) => {
  if (event.data && event.data.type === 'MSG_ID') {
    //process message...
  }
};

Görüldüğü gibi, belirli bir bağlama dair açık bir referans olmadığından hizmet çalışanına veya belirli bir istemciye atıfta bulunmalıdır.

Yayın Kanalı nesnesi kullanarak sayfa ve hizmet çalışanı arasındaki iki yönlü iletişimi gösteren şema.

Dezavantajı ise bu yazıyı yazıldığı anda API'nin Chrome, Firefox ve Edge gibi tarayıcılar desteklenmektedir, ancak Safari gibi diğer tarayıcılar bunu desteklemez. (henüz).

İstemci API'si

Tarayıcı Desteği

  • Chrome: 40.
  • Kenar: 17.
  • Firefox: 44.
  • Safari: 11.1

Kaynak

Client API, hizmet çalışanının kontrol ettiği etkin sekmeleri temsil eden tüm WindowClient nesnelerine referans verir.

Sayfa tek bir hizmet çalışanı tarafından kontrol edildiğinden mesajları dinler ve şuraya gönderir: aktif hizmet çalışanı, doğrudan serviceWorker arayüzü üzerinden:

//send message
navigator.serviceWorker.controller.postMessage({
  type: 'MSG_ID',
});

//listen to messages
navigator.serviceWorker.onmessage = (event) => {
  if (event.data && event.data.type === 'MSG_ID') {
    //process response
  }
};

Benzer şekilde, hizmet çalışanı bir onmessage işleyici uygulayarak mesajları dinler:

//listen to messages
self.addEventListener('message', (event) => {
  if (event.data && event.data.type === 'MSG_ID') {
    //Process message
  }
});

Service Worker, müşterilerinden herhangi biriyle iletişim kurmak için elindeki Yürüterek WindowClient nesne izleme araçları ve Clients.matchAll() ve Clients.get(). Sonra da Aşağıdakilerden herhangi birini postMessage():

//Obtain an array of Window client objects
self.clients.matchAll(options).then(function (clients) {
  if (clients && clients.length) {
    //Respond to last focused tab
    clients[0].postMessage({type: 'MSG_ID'});
  }
});
Bir hizmet çalışanının bir dizi istemciyle iletişimini gösteren şema.

Client API, bir hizmet çalışanının tüm etkin sekmeleriyle kolayca iletişim kurmak için iyi bir seçenektir hem de nispeten kolay bir şekilde yapabilirsiniz. Bu API, tüm büyük daha fazla bilgi edinin. ancak tüm yöntemleri mevcut olmayabilir. Bu nedenle, başlamadan önce tarayıcı desteğini kontrol etmeyi nasıl uygulayacağınızı öğreneceksiniz.

Mesaj Kanalı

Tarayıcı Desteği

  • Chrome: 2.
  • Kenar: 12.
  • Firefox: 41.
  • Safari: 5.

Kaynak

Mesaj Kanalı için gerekenler iki yönlü iletişim kurmak için bir bağlantı noktasını tanımlama ve bir bağlamdan diğerine aktarma yardımcı olur.

Sayfa, kanalı başlatmak için bir MessageChannel nesnesi örneklendirir ve bunu kullanır. kayıtlı hizmet çalışanına bir bağlantı noktası gönderin. Sayfa şuna bir onmessage işleyicisi de uygular: diğer bağlamdan mesaj almak için:

const messageChannel = new MessageChannel();

//Init port
navigator.serviceWorker.controller.postMessage({type: 'PORT_INITIALIZATION'}, [
  messageChannel.port2,
]);

//Listen to messages
messageChannel.port1.onmessage = (event) => {
  // Process message
};
İki yönlü iletişim kurmak için bir bağlantı noktasını Service Worker'a geçiren bir sayfayı gösteren şema.

Hizmet çalışanı bağlantı noktasını alır, ona bir referans kaydeder ve diğer taraf:

let communicationPort;

//Save reference to port
self.addEventListener('message', (event) => {
  if (event.data && event.data.type === 'PORT_INITIALIZATION') {
    communicationPort = event.ports[0];
  }
});

//Send messages
communicationPort.postMessage({type: 'MSG_ID'});

MessageChannel şu anda tüm ana dallar tarafından desteklenmektedir tarayıcıları kullanın.

Gelişmiş API'lar: Arka Plan Senkronizasyonu ve Arka Planda Getirme

Bu kılavuzda, nispeten büyük bir şirket için iki yönlü iletişim tekniklerinin basit durumlar (ör. gerçekleştirilecek işlemi açıklayan bir dize mesajı veya bir URL listesi iletme) . Bu bölümde, belirli işlemleri yapmak için iki API'yi bazı senaryolar: bağlantı eksikliği ve uzun indirmeler.

Arka Plan Senkronizasyonu

Tarayıcı Desteği

  • Chrome: 49.
  • Kenar: 79.
  • Firefox: Desteklenmez.
  • Safari: desteklenmez.

Kaynak

Bir sohbet uygulaması, mesajların zayıf bağlantı nedeniyle kaybolmadığından emin olmak isteyebilir. İlgili içeriği oluşturmak için kullanılan Arka Plan Senkronizasyonu API'sı şunları yapmanıza olanak tanır: kullanıcının kararlı bir bağlantısı olduğunda yeniden denenecek işlemleri ertele. Bu sayede proje zaman çizelgesinde gönderilen bir şeydir.

postMessage() arayüzü yerine, sayfa bir sync kaydeder:

navigator.serviceWorker.ready.then(function (swRegistration) {
  return swRegistration.sync.register('myFirstSync');
});

Ardından hizmet çalışanı, mesajı işlemek için sync etkinliğini dinler:

self.addEventListener('sync', function (event) {
  if (event.tag == 'myFirstSync') {
    event.waitUntil(doSomeStuff());
  }
});

doSomeStuff() işlevi, amacının başarılı/başarısız olduğunu belirten bir vaat döndürmelidir. yapmaya çalışıyorsunuz. İstek yerine getirilirse senkronizasyon tamamlanmıştır. Başarısız olursa başka bir senkronizasyon işlemi yeniden dene. Yeniden deneme senkronizasyonları da bağlantı kurulmasını bekler ve eksponansiyel geri çekme uygular.

İşlem yapıldıktan sonra Service Worker, sayfayla iletişim kurarak daha önce keşfedilen iletişim API'lerinden herhangi birini kullanarak kullanıcı arayüzünü güncelleyin.

Google Arama, zayıf bağlantı nedeniyle başarısız olan sorguları sürdürmek için Arka Plan Senkronizasyonu'nu kullanır ve işlemi yeniden dener. daha sonra kullanıcı çevrimiçi olduğunda düzenleyebilir. İşlem gerçekleştirildikten sonra sonucu kullanıcıya web push bildirimiyle:

İki yönlü iletişim kurmak için bir bağlantı noktasını Service Worker'a geçiren bir sayfayı gösteren şema.

Arka Planda Getirme

Tarayıcı Desteği

  • Chrome: 74.
  • Kenar: 79.
  • Firefox: Desteklenmez.
  • Safari: desteklenmez.

Kaynak

İleti gönderme veya önbelleğe alınacak URL listesi gibi nispeten kısa işler için iyi bir seçim olabilir. Görev çok uzun sürerse tarayıcı hizmeti sonlandıracaktır aksi takdirde kullanıcının gizliliği ve pili açısından risk söz konusudur.

Arka Plan Getirme API'si film, podcast veya seviye indirme gibi uzun bir görevi hizmet çalışanına boşaltmanızı sağlar bir oyundur.

Hizmet çalışanıyla sayfadan iletişim kurmak için şunun yerine backgroundFetch.fetch kullanın: postMessage():

navigator.serviceWorker.ready.then(async (swReg) => {
  const bgFetch = await swReg.backgroundFetch.fetch(
    'my-fetch',
    ['/ep-5.mp3', 'ep-5-artwork.jpg'],
    {
      title: 'Episode 5: Interesting things.',
      icons: [
        {
          sizes: '300x300',
          src: '/ep-5-icon.png',
          type: 'image/png',
        },
      ],
      downloadTotal: 60 * 1024 * 1024,
    },
  );
});

BackgroundFetchRegistration nesnesi, sayfanın takip etmek üzere progress etkinliğini dinlemesine olanak tanır indirme işleminin ilerleme durumu:

bgFetch.addEventListener('progress', () => {
  // If we didn't provide a total, we can't provide a %.
  if (!bgFetch.downloadTotal) return;

  const percent = Math.round(
    (bgFetch.downloaded / bgFetch.downloadTotal) * 100,
  );
  console.log(`Download progress: ${percent}%`);
});
İki yönlü iletişim kurmak için bir bağlantı noktasını Service Worker'a geçiren bir sayfayı gösteren şema.
Kullanıcı arayüzü, indirme işleminin ilerleme durumunu gösterecek şekilde güncellenir (solda). Service Worker'lar sayesinde tüm sekmeler kapatıldığında (sağda) işlem çalışmaya devam edebilir.
ziyaret edin.

Sonraki adımlar

Bu kılavuzda, sayfa ve hizmet çalışanları arasındaki iletişimin en genel durumunu inceledik. (çift yönlü iletişim).

Çoğu zaman bir kişinin diğeriyle iletişim kurmak için yalnızca bir bağlama ihtiyaç duyduğunda, tıklayın. Sektörde tek yönlü tekniklerin nasıl uygulanacağıyla ilgili yol gösterici bilgiler için aşağıdaki kılavuzlara göz atın: kullanım alanları ve üretim örnekleriyle birlikte hizmet çalışanına ve hizmet çalışanına giden sayfalarınız:

  • Zorunlu önbelleğe alma rehberi: kaynaklarını önceden önbelleğe almanız gerekir (ör. önceden getirme senaryolarında).
  • Yayın güncellemeleri: Bilgilendirmek için hizmet çalışanından sayfanın çağrılması Önemli güncellemeler hakkında (ör. web uygulamasının yeni bir sürümünün mevcut olması)