Arka Plan Getirme ile tanışın

Jake Archibald
Jake Archibald

2015'te, hizmet çalışanının kullanıcının bağlantısı olana kadar işi ertelemelerine olanak tanıyan Arka Plan Senkronizasyonu'nu kullanıma sunduk. Bu sayede kullanıcı bir mesaj yazıp gönder düğmesine basabilir ve mesajın hemen veya bağlantısı olduğunda gönderileceğini bilerek siteden ayrılabilir.

Bu kullanışlı bir özelliktir ancak getirme işlemi sırasında hizmet çalışanının etkin olması gerekir. Bu, mesaj gönderme gibi kısa işlemler için sorun oluşturmaz ancak görev çok uzun sürerse tarayıcı hizmet çalışanını sonlandırır. Aksi takdirde, kullanıcının gizliliği ve pili için risk oluşur.

Peki film, podcast veya oyun seviyeleri gibi uzun süren bir indirme işleminiz varsa ne yapabilirsiniz? Arka planda getirme bu sorunu çözmek için tasarlanmıştır.

Arka Planda Getirme, Chrome 74'ten itibaren varsayılan olarak kullanılabilir.

Aşağıda, arka planda getirme özelliğinin kullanılmadığı ve kullanıldığı durumları gösteren iki dakikalık kısa bir demo verilmiştir:

Demoyu kendiniz deneyin ve koda göz atın.

İşleyiş şekli

Arka planda getirme işlemi şu şekilde işler:

  1. Tarayıcıya arka planda bir grup getirme işlemi gerçekleştirmesini söylersiniz.
  2. Tarayıcı bu öğeleri getirir ve kullanıcıya ilerleme durumunu gösterir.
  3. Getirme işlemi tamamlandığında veya başarısız olduğunda tarayıcı, servis çalışanınızı açar ve ne olduğunu size bildirmek için bir etkinlik tetikler. Yanıtlarla (varsa) ne yapacağınıza burada karar verirsiniz.

Kullanıcı 1. adımdan sonra sitenizin sayfalarını kapatırsa indirme işlemi devam eder. Getirme işlemi çok görünür olduğundan ve kolayca iptal edilebildiğinden, çok uzun süren arka plan senkronizasyonu görevi nedeniyle gizlilikle ilgili endişeler yaşanmaz. Hizmet çalışanı sürekli çalışmadığından, arka planda bitcoin madenciliği yapmak gibi sistemi kötüye kullanabileceği konusunda endişelenmenize gerek yoktur.

Bazı platformlarda (ör. Android), tarayıcı getirme işlemini işletim sistemine devredebileceğinden 1. adımdan sonra kapanabilir.

Kullanıcı indirme işlemini çevrimdışıyken başlatırsa veya indirme sırasında çevrimdışı olursa arka planda getirme duraklatılır ve daha sonra devam ettirilir.

API

Özellik algılama

Her yeni özellikte olduğu gibi, tarayıcının bu özelliği destekleyip desteklemediğini algılamak istersiniz. Arka planda getirme için yapmanız gerekenler:

if ('BackgroundFetchManager' in self) {
  // This browser supports Background Fetch!
}

Arka planda getirme işlemini başlatma

Ana API, bir Service Worker kaydına bağlıdır. Bu nedenle, önce bir Service Worker kaydettiğinizden emin olun. Ardından:

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

backgroundFetch.fetch üç bağımsız değişken alır:

Parametreler
id string
, bu arka plan getirme işlemini benzersiz bir şekilde tanımlar.

Kimlik mevcut bir arka plan getirme işlemiyle eşleşirse backgroundFetch.fetch reddeder.

requests Array<Request|string>
Getirilecek öğeler. Dizeler URL olarak değerlendirilir ve new Request(theString) aracılığıyla Request olarak dönüştürülür.

Kaynaklar izin verdiği sürece CORS aracılığıyla diğer kaynaklardan öğe getirebilirsiniz.

Not: Chrome şu anda CORS ön uçuş gerektiren istekleri desteklememektedir.

options Aşağıdakileri içerebilen bir nesne:
options.title string
Tarayıcının ilerleme durumunu göstereceği başlık.
options.icons Array<IconDefinition>
"src", "size" ve "type" değerlerine sahip bir nesne dizisi.
options.downloadTotal number
Yanıt gövdelerinin toplam boyutu (sıkıştırma kaldırıldıktan sonra).

Bu isteğe bağlıdır ancak sağlamanız önemle tavsiye edilir. Kullanıcıya indirme işleminin ne kadar büyük olduğunu bildirmek ve ilerleme durumu bilgisi sağlamak için kullanılır. Bu bilgiyi sağlamazsanız tarayıcı, kullanıcıya boyutun bilinmediğini söyler. Bu durumda kullanıcının indirme işlemini iptal etme olasılığı artar.

Arka planda getirme işlemi, burada belirtilen sayıyı aşarsa iptal edilir. İndirme işlemi downloadTotal'ten küçükse bu durum sorun teşkil etmez. İndirme işleminin toplam boyutundan emin değilseniz tedbirli davranmanız önerilir.

backgroundFetch.fetch, BackgroundFetchRegistration ile çözülen bir promise döndürür. Ayrıntıları daha sonra ele alacağız. Kullanıcı indirmeleri devre dışı bıraktıysa veya sağlanan parametrelerden biri geçersizse söz verme işlemi reddedilir.

Tek bir arka plan getirme işlemi için birçok istek göndermek, kullanıcı için mantıksal olarak tek bir şey olan öğeleri birleştirmenize olanak tanır. Örneğin, bir film 1.000'lerce kaynağa bölünebilir (MPEG-DASH ile yaygındır) ve resimler gibi ek kaynaklar içerebilir. Bir oyunun seviyesi birçok JavaScript, resim ve ses kaynağına yayılabilir. Ancak kullanıcı için bu "film" veya "seviye"dir.

Mevcut bir arka planda getirme işlemini alma

Mevcut bir arka plan getirme işlemini şu şekilde alabilirsiniz:

navigator.serviceWorker.ready.then(async (swReg) => {
  const bgFetch = await swReg.backgroundFetch.get('my-fetch');
});

İstediğiniz arka plan getirme işleminin kimliğini ileterek Söz konusu kimlikle etkin bir arka plan getirme işlemi yoksa get undefined değerini döndürür.

Arka planda getirme işlemi, kaydedildiği andan itibaren başarılı olana, başarısız olana veya iptal edilene kadar "etkin" olarak kabul edilir.

getIds kullanarak tüm etkin arka plan getirme işlemlerinin listesini alabilirsiniz:

navigator.serviceWorker.ready.then(async (swReg) => {
  const ids = await swReg.backgroundFetch.getIds();
});

Arka planda getirme kayıtları

BackgroundFetchRegistration (yukarıdaki örneklerde bgFetch), aşağıdakileri içerir:

Özellikler
id string
Arka planda getirme işleminin kimliği.
uploadTotal number
Sunacuya gönderilecek bayt sayısı.
uploaded number
Başarıyla gönderilen bayt sayısı.
downloadTotal number
Arka planda getirme işlemi kaydedilirken sağlanan değer veya sıfır.
downloaded number
Başarıyla alınan bayt sayısı.

Bu değer düşebilir. Örneğin, bağlantı kesilirse ve indirme işlemi devam ettirilemezse tarayıcı, söz konusu kaynağın getirilmesini sıfırdan başlatır.

result

Aşağıdakilerden biri:

  • "": Arka planda getirme etkin olduğu için henüz sonuç yok.
  • "success": Arka planda getirme işlemi başarılı oldu.
  • "failure": Arka planda getirme işlemi başarısız oldu. Bu değer yalnızca arka planda getirme işlemi tamamen başarısız olduğunda görünür.
failureReason

Aşağıdakilerden biri:

  • "": Arka planda getirme işlemi başarısız olmadı.
  • "aborted": Arka planda getirme işlemi kullanıcı tarafından iptal edildi veya abort() çağrıldı.
  • "bad-status": Yanıtlardan biri "ok" durumuna sahip değildi (ör. 404).
  • "fetch-error": Getirme işlemlerinden biri başka bir nedenle başarısız oldu (ör. CORS, MIX, geçersiz kısmi yanıt veya yeniden denenemeyen bir getirme işlemi için genel ağ hatası).
  • "quota-exceeded": Arka planda getirme sırasında depolama alanı kotasına ulaşıldı.
  • "download-total-exceeded": Sağlanan "downloadTotal" değeri aşıldı.
recordsAvailable boolean
Temel isteklere/yanıtlara erişilebilir mi?

Bu değer yanlış olduğunda match ve matchAll kullanılamaz.

Yöntemler
abort() Promise<boolean>
döndürür. Arka planda getirme işlemini iptal eder.

Getirme işlemi başarıyla iptal edildiyse döndürülen promise true ile çözülür.

matchAll(request, opts) Döndürülen değer Promise<Array<BackgroundFetchRecord>>
İstekleri ve yanıtları alın.

Buradaki bağımsız değişkenler, önbellek API'siyle aynıdır. Bağımsız değişken olmadan çağrıldığında tüm kayıtlar için bir promise döndürülür.

Daha ayrıntılı bilgi edinmek için aşağıdaki bölümü inceleyin.

match(request, opts) Promise<BackgroundFetchRecord> döndürür
Yukarıdaki gibidir ancak ilk eşleşmeyle çözünür.
Etkinlikler
progress uploaded, downloaded, result veya failureReason değiştiğinde tetiklenir.

İlerleme durumunu izleme

Bu işlem, progress etkinliği aracılığıyla yapılabilir. downloadTotal değerinin, belirttiğiniz değeri veya değer belirtmediyseniz 0 değerini ifade ettiğini unutmayın.

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

İstekleri ve yanıtları alma

bgFetch.match('/ep-5.mp3').then(async (record) => {
  if (!record) {
    console.log('No record found');
    return;
  }

  console.log(`Here's the request`, record.request);
  const response = await record.responseReady;
  console.log(`And here's the response`, response);
});

record bir BackgroundFetchRecord'dir ve şu şekilde görünür:

Özellikler
request Request
Sağlanan istek.
responseReady Promise<Response>
Getirilen yanıt.

Yanıt henüz alınmamış olabileceği için söz verilen sürede gönderilmemiştir. Getirme işlemi başarısız olursa söz

Hizmet çalışanı etkinlikleri

Etkinlikler
backgroundfetchsuccess Tüm veriler başarıyla getirildi.
backgroundfetchfailure Getirme işlemlerinden biri veya daha fazlası başarısız oldu.
backgroundfetchabort Bir veya daha fazla getirme işlemi başarısız oldu.

Bu işlem, yalnızca ilgili verileri temizlemek istiyorsanız faydalıdır.

backgroundfetchclick Kullanıcı, indirme ilerleme durumunu gösteren kullanıcı arayüzünü tıkladı.

Etkinlik nesneleri şunları içerir:

Özellikler
registration BackgroundFetchRegistration
Yöntemler
updateUI({ title, icons }) İlk olarak ayarladığınız başlığı/simgeleri değiştirmenize olanak tanır. Bu isteğe bağlıdır ancak gerekirse daha fazla bağlam bilgisi eklemenize olanak tanır. Bu işlemi backgroundfetchsuccess ve backgroundfetchfailure etkinlikleri sırasında yalnızca *bir kez* yapabilirsiniz.

Başarıya/başarısızlığa tepki verme

progress etkinliğini daha önce görmüştük ancak bu etkinlik yalnızca kullanıcının sitenizde açık bir sayfası olduğunda faydalıdır. Arka planda getirmenin en büyük avantajı, kullanıcı sayfadan ayrıldıktan veya hatta tarayıcıyı kapattıktan sonra işlemlerin çalışmaya devam etmesidir.

Arka planda getirme işlemi başarıyla tamamlanırsa servis çalışanınız backgroundfetchsuccess etkinliğini alır ve event.registration, arka planda getirme kaydı olur.

Bu olaydan sonra getirilen istek ve yanıtlara artık erişilemez. Bu nedenle, saklamak istediğiniz istek ve yanıtları önbellek API'si gibi bir yere taşıyın.

Çoğu hizmet çalışanı etkinliğinde olduğu gibi, hizmet çalışanının etkinliğin ne zaman tamamlandığını bilmesi için event.waitUntil değerini kullanın.

Örneğin, servis çalışanınızda:

addEventListener('backgroundfetchsuccess', (event) => {
  const bgFetch = event.registration;

  event.waitUntil(async function() {
    // Create/open a cache.
    const cache = await caches.open('downloads');
    // Get all the records.
    const records = await bgFetch.matchAll();
    // Copy each request/response across.
    const promises = records.map(async (record) => {
      const response = await record.responseReady;
      await cache.put(record.request, response);
    });

    // Wait for the copying to complete.
    await Promise.all(promises);

    // Update the progress notification.
    event.updateUI({ title: 'Episode 5 ready to listen!' });
  }());
});

Başarısızlık, sizin için önemli olmayabilecek tek bir 404 hatasından kaynaklanmış olabilir. Bu nedenle, bazı yanıtları yukarıdaki gibi bir önbelleğe kopyalamak yine de faydalı olabilir.

Tıklamalara tepki verme

İndirme işleminin ilerleme durumunu ve sonucunu gösteren kullanıcı arayüzü tıklanabilir. Hizmet çalışanındaki backgroundfetchclick etkinliği, buna tepki vermenize olanak tanır. Yukarıda belirtildiği gibi event.registration, kayıtları arka planda getirme işlemidir.

Bu olayla ilgili olarak genellikle bir pencere açılır:

addEventListener('backgroundfetchclick', (event) => {
  const bgFetch = event.registration;

  if (bgFetch.result === 'success') {
    clients.openWindow('/latest-podcasts');
  } else {
    clients.openWindow('/download-progress');
  }
});

Ek kaynaklar

Düzeltme: Bu makalenin önceki bir sürümünde Arka Planda Getirme özelliği "web standardı" olarak yanlış bir şekilde belirtilmişti. API şu anda standartlar kapsamında değil. Şartname, WICG'de taslak topluluk grubu raporu olarak bulunabilir.