API Siklus Proses Halaman

Dukungan Browser

  • Chrome: 68.
  • Edge: 79.
  • Firefox: tidak didukung.
  • Safari: tidak didukung.

{i>Browser<i} modern saat ini terkadang akan menangguhkan laman atau membuangnya sepenuhnya ketika resource sistem dibatasi. Di masa mendatang, browser akan melakukan ini secara proaktif, sehingga mereka memakai lebih sedikit daya dan memori. Page Lifecycle API menyediakan hook siklus proses sehingga halaman Anda dapat menangani browser ini dengan aman intervensi tanpa mempengaruhi pengalaman pengguna. Lihat API untuk melihat apakah Anda harus mengimplementasikan fitur-fitur ini dalam aplikasi Anda.

Latar belakang

Siklus hidup aplikasi adalah cara utama yang dikelola sistem operasi modern Google Cloud Platform. Di Android, iOS, dan versi Windows terbaru, aplikasi dapat dimulai dan dihentikan kapan saja oleh OS. Hal ini memungkinkan platform ini untuk menyederhanakan dan mengalokasikan ulang sumber daya ke tempat yang memberikan manfaat terbaik bagi pengguna.

Di web, secara historis tidak ada siklus proses seperti itu, dan aplikasi dapat dipertahankan hidup tanpa batas. Dengan sejumlah besar laman web yang sedang berjalan, sistem penting seperti memori, CPU, baterai, dan jaringan bisa menjadi langganan berlebihan, yang menyebabkan pengalaman pengguna akhir yang buruk.

Platform web telah lama mengalami peristiwa yang terkait dengan status siklus proses — seperti load, unload, dan visibilitychange — acara ini hanya mengizinkan developer untuk merespons perubahan status siklus proses yang dimulai oleh pengguna. Agar web dapat berfungsi andal pada perangkat bertenaga rendah (dan lebih sadar akan sumber daya secara umum semua platform) browser memerlukan cara untuk secara proaktif mengklaim kembali dan mengalokasikan ulang sistem Google Cloud Platform.

Faktanya, browser saat ini sudah mengambil tindakan aktif untuk menghemat resource untuk halaman di tab latar belakang, dan banyak browser (terutama Chrome) yang menginginkan untuk melakukan lebih banyak hal ini — untuk mengurangi jejak resource mereka secara keseluruhan.

Masalahnya, pengembang tidak memiliki cara untuk mempersiapkan diri menghadapi jenis intervensi yang dimulai oleh sistem atau bahkan mengetahui bahwa itu sedang terjadi. Artinya browser harus konservatif atau berisiko merusak laman web.

Page Lifecycle API mencoba memecahkan masalah ini dengan:

  • Memperkenalkan dan menstandardisasi konsep status siklus proses di web.
  • Mendefinisikan status baru yang dimulai oleh sistem yang memungkinkan browser membatasi yang dapat dipakai oleh tab tersembunyi atau tidak aktif.
  • Membuat API dan peristiwa baru yang memungkinkan developer web merespons bertransisi ke dan dari status yang dimulai oleh sistem ini.

Solusi ini memberikan prediktabilitas yang dibutuhkan developer web untuk membangun lebih tangguh terhadap intervensi sistem, dan memungkinkan browser untuk lebih mengoptimalkan resource sistem secara agresif, yang pada akhirnya menguntungkan semua pengguna web.

Bagian selanjutnya dari postingan ini akan memperkenalkan fitur Siklus Proses Halaman yang baru dan mengeksplorasi bagaimana mereka berhubungan dengan semua status platform web yang ada dan peristiwa. Dasbor ini juga akan memberikan rekomendasi dan praktik terbaik untuk jenis pekerjaan yang seharusnya (dan tidak boleh) dilakukan pengembang di setiap negara bagian.

Ringkasan status dan peristiwa Siklus Proses Halaman

Semua status Siklus Proses Halaman bersifat terpisah dan sama-sama bersifat eksklusif, artinya halaman hanya bisa berada dalam satu keadaan dalam satu waktu. Dan sebagian besar perubahan pada status siklus proses halaman umumnya dapat diamati melalui peristiwa DOM (lihat rekomendasi developer untuk setiap status untuk pengecualian).

Mungkin cara termudah untuk menjelaskan status Siklus Proses Halaman — serta peristiwa yang menandakan transisi di antaranya — adalah dengan diagram:

Representasi visual status dan alur peristiwa yang dijelaskan di seluruh dokumen ini.
Status dan alur peristiwa Page Lifecycle API.

Negara bagian

Tabel berikut menjelaskan setiap status secara mendetail. Kolom ini juga mencantumkan kemungkinan yang bisa muncul sebelum dan sesudah serta peristiwa yang dapat developer gunakan untuk mengamati perubahan.

Negara Bagian Deskripsi
Aktif

Halaman berada dalam status aktif jika terlihat dan memiliki fokus input.

Kemungkinan status sebelumnya:
pasif (melalui acara focus)
dibekukan (melalui peristiwa resume, kemudian pageshow)

Kemungkinan status berikutnya:
pasif (melalui acara blur)

Pasif

Halaman berada dalam status pasif jika terlihat dan tidak memiliki fokus input.

Kemungkinan status sebelumnya:
aktif (melalui acara blur)
tersembunyi (melalui visibilitychange)
dibekukan (melalui peristiwa resume, kemudian pageshow)

Kemungkinan status berikutnya:
aktif (melalui acara focus)
tersembunyi (melalui visibilitychange)

Tersembunyi

Halaman berada dalam status tersembunyi jika tidak terlihat (dan belum dibekukan, dibuang, atau dihentikan).

Kemungkinan status sebelumnya:
pasif (melalui visibilitychange)
dibekukan (melalui peristiwa resume, kemudian pageshow)

Kemungkinan status berikutnya:
pasif (melalui visibilitychange)
dibekukan (melalui peristiwa freeze)
dihapus (tidak ada peristiwa yang diaktifkan)
dihentikan (tidak ada peristiwa yang diaktifkan)

Beku

Dalam keadaan beku, browser menangguhkan eksekusi dapat dibekukan tugas di dokumen task queue hingga halaman dibekukan. Ini berarti hal-hal seperti Timer JavaScript dan callback pengambilan tidak berjalan. Sudah berjalan tugas-tugas ini dapat diselesaikan (yang terpenting freeze), tetapi jumlahnya mungkin terbatas. dapat mereka lakukan dan berapa lama bisa berjalan.

Browser membekukan halaman sebagai cara untuk menghemat penggunaan CPU/baterai/data; mereka juga dilakukan sebagai cara untuk memungkinkan lebih cepat navigasi mundur/maju — menghindari kebutuhan akan tampilan halaman penuh memuat ulang.

Kemungkinan status sebelumnya:
disembunyikan (melalui acara freeze)

Kemungkinan status berikutnya:
aktif (melalui acara resume, kemudian pageshow peristiwa)
pasif (melalui acara resume, kemudian pageshow peristiwa)
tersembunyi (melalui acara resume)
dihapus (tidak ada peristiwa yang diaktifkan)

Dihentikan

Halaman berada dalam status dihentikan setelah mulai dihapus muatannya dan dihapus dari memori oleh browser. Lain kali tugas baru dapat dimulai dalam status ini, dan tugas yang sedang berlangsung mungkin akan dihentikan jika terlalu lama.

Kemungkinan status sebelumnya:
disembunyikan (melalui acara pagehide)

Kemungkinan status berikutnya:
TIDAK ADA

Dihapus

Halaman berada dalam status dihapus saat dihapus muatannya oleh {i>browser<i} Anda untuk menghemat sumber daya. Tanpa tugas, callback peristiwa, atau JavaScript apa pun dapat berjalan dalam status ini, seperti yang dibuang biasanya terjadi karena keterbatasan sumber daya, di mana memulai proses baru mustahil.

Dalam status dihapus, tab itu sendiri (termasuk judul tab dan favicon) biasanya dapat dilihat oleh pengguna meskipun halaman hilang.

Kemungkinan status sebelumnya:
disembunyikan (tidak ada peristiwa yang diaktifkan)
dibekukan (tidak ada peristiwa yang diaktifkan)

Kemungkinan status berikutnya:
TIDAK ADA

Acara

Browser mengirim banyak peristiwa, tetapi hanya sebagian kecil yang menandakan kemungkinan perubahan status Siklus Proses Halaman. Tabel berikut menguraikan semua peristiwa yang berkaitan dengan siklus proses dan berisi daftar status yang dapat menjadi tujuan transisi mereka.

Nama Detail
focus

Elemen DOM menerima fokus.

Catatan: peristiwa focus tidak selalu menandakan perubahan status. Sinyal ini hanya mengisyaratkan perubahan status jika halaman sebelumnya tidak memiliki fokus input.

Kemungkinan status sebelumnya:
pasif

Kemungkinan status saat ini:
aktif

blur

Elemen DOM kehilangan fokus.

Catatan: peristiwa blur tidak selalu menandakan perubahan status. Sinyal ini hanya mengisyaratkan perubahan status jika halaman tidak lagi memiliki fokus input (yaitu halaman tidak hanya beralih fokus dari satu elemen ke elemen lainnya).

Kemungkinan status sebelumnya:
aktif

Kemungkinan status saat ini:
pasif

visibilitychange

Nilai visibilityState telah diubah. Hal ini dapat terjadi saat pengguna menavigasi ke laman baru, beralih tab, menutup tab, meminimalkan atau menutup browser, atau beralih aplikasi saat menggunakan perangkat seluler yang berbeda.

Kemungkinan status sebelumnya:
pasif
disembunyikan

Kemungkinan status saat ini:
pasif
disembunyikan

freeze *

Halaman baru saja dibekukan. Apa saja tugas yang dapat dibekukan di task queue halaman tidak akan dimulai.

Kemungkinan status sebelumnya:
disembunyikan

Kemungkinan status saat ini:
dibekukan

resume *

Browser telah melanjutkan halaman beku.

Kemungkinan status sebelumnya:
dibekukan

Kemungkinan status saat ini:
aktif (jika diikuti dengan pageshow)
pasif (jika diikuti dengan pageshow)
tersembunyi

pageshow

Entri histori sesi yang sedang dijelajahi.

Hal ini dapat berupa pemuatan halaman baru atau halaman yang diambil dari back/forward cache. Jika halaman diambil dari back-forward cache, Properti persisted adalah true, jika tidak, properti ini false.

Kemungkinan status sebelumnya:
dibekukan (resume peristiwa juga akan aktif)

Kemungkinan status saat ini:
aktif
pasif
disembunyikan

pagehide

Entri histori sesi yang dilintasi.

Jika pengguna menavigasi ke laman lain dan browser dapat menambahkan halaman saat ini ke bagian mundur/maju cache untuk digunakan kembali nanti, properti persisted peristiwa adalah true. Saat true, halaman memasuki status beku, jika tidak, memasuki status dihentikan.

Kemungkinan status sebelumnya:
disembunyikan

Kemungkinan status saat ini:
dibekukan (event.persisted benar, freeze mengikuti)
dihentikan (event.persisted salah, unload peristiwa mengikuti)

beforeunload

Jendela, dokumen, dan resource-nya akan dihapus muatannya. Dokumen masih terlihat dan acara masih dapat dibatalkan pada saat ini poin.

Penting: peristiwa beforeunload sebaiknya hanya digunakan untuk memberi tahu pengguna tentang perubahan yang belum disimpan. Setelah perubahan disimpan, acara tersebut harus dihapus. Seharusnya tidak pernah yang ditambahkan tanpa syarat ke halaman, karena dapat mengganggu performa dalam beberapa kasus. Lihat versi lama bagian API untuk mengetahui detailnya.

Kemungkinan status sebelumnya:
disembunyikan

Kemungkinan status saat ini:
dihentikan

unload

Halaman sedang dihapus muatannya.

Peringatan: menggunakan peristiwa unload tidak pernah direkomendasikan karena tidak dapat diandalkan dan dalam kasus tertentu dapat mengganggu performa. Lihat bagian API lama untuk mengetahui detail selengkapnya.

Kemungkinan status sebelumnya:
disembunyikan

Kemungkinan status saat ini:
dihentikan

* Menunjukkan peristiwa baru yang ditentukan oleh Page Lifecycle API

Fitur baru yang ditambahkan di Chrome 68

Diagram sebelumnya menunjukkan dua status yang dimulai oleh sistem, bukan dimulai oleh pengguna: dibekukan dan dihapus. Seperti yang disebutkan sebelumnya, browser saat ini terkadang membekukan dan membuang tab tersembunyi (sesuai pertimbangan mereka), tetapi developer tidak dapat mengetahui kapan hal ini sedang terjadi.

Di Chrome 68, developer kini dapat mengamati saat tab tersembunyi dibekukan dan diproses kembali dengan memproses freeze dan peristiwa resume pada document.

document.addEventListener('freeze', (event) => {
  // The page is now frozen.
});

document.addEventListener('resume', (event) => {
  // The page has been unfrozen.
});

Dari Chrome 68, objek document kini menyertakan wasDiscarded di Chrome desktop (dukungan Android dilacak dalam masalah ini). Untuk menentukan apakah halaman dihapus saat berada di browser tersembunyi , Anda dapat memeriksa nilai properti ini pada waktu pemuatan halaman (catatan: halaman yang dihapus harus dimuat ulang agar dapat digunakan lagi).

if (document.wasDiscarded) {
  // Page was previously discarded by the browser while in a hidden tab.
}

Untuk saran tentang hal-hal penting yang perlu dilakukan di freeze dan resume peristiwa, serta cara menangani dan mempersiapkan laman yang dihapus, lihat rekomendasi developer untuk setiap negara bagian.

Beberapa bagian selanjutnya menawarkan ikhtisar tentang bagaimana fitur-fitur baru ini sesuai dengan status dan peristiwa platform web yang ada.

Cara mengamati status Siklus Proses Halaman dalam kode

Dalam mode active, pasif, dan hidden status, Anda dapat menjalankan kode JavaScript yang menentukan Status Siklus Proses Halaman dari API platform web yang ada.

const getState = () => {
  if (document.visibilityState === 'hidden') {
    return 'hidden';
  }
  if (document.hasFocus()) {
    return 'active';
  }
  return 'passive';
};

Status beku dan dihentikan, di sisi lain, hanya dapat dideteksi di pemroses peristiwanya masing-masing (freeze dan pagehide) sebagaimana negara bagian berganti.

Cara mengamati perubahan status

Dengan menggunakan fungsi getState() yang ditentukan sebelumnya, Anda dapat mengamati semua Halaman Status siklus proses berubah dengan kode berikut.

// Stores the initial state using the `getState()` function (defined above).
let state = getState();

// Accepts a next state and, if there's been a state change, logs the
// change to the console. It also updates the `state` value defined above.
const logStateChange = (nextState) => {
  const prevState = state;
  if (nextState !== prevState) {
    console.log(`State change: ${prevState} >>> ${nextState}`);
    state = nextState;
  }
};

// Options used for all event listeners.
const opts = {capture: true};

// These lifecycle events can all use the same listener to observe state
// changes (they call the `getState()` function to determine the next state).
['pageshow', 'focus', 'blur', 'visibilitychange', 'resume'].forEach((type) => {
  window.addEventListener(type, () => logStateChange(getState()), opts);
});

// The next two listeners, on the other hand, can determine the next
// state from the event itself.
window.addEventListener('freeze', () => {
  // In the freeze event, the next state is always frozen.
  logStateChange('frozen');
}, opts);

window.addEventListener('pagehide', (event) => {
  // If the event's persisted property is `true` the page is about
  // to enter the back/forward cache, which is also in the frozen state.
  // If the event's persisted property is not `true` the page is
  // about to be unloaded.
  logStateChange(event.persisted ? 'frozen' : 'terminated');
}, opts);

Kode ini melakukan tiga hal:

  • Menetapkan status awal menggunakan fungsi getState().
  • Menentukan fungsi yang menerima status berikutnya dan, jika terjadi perubahan, mencatat perubahan status ke konsol.
  • Penambahan mengambil foto pemroses peristiwa untuk semua peristiwa siklus proses yang diperlukan, yang akan memanggil logStateChange(), yang meneruskan status berikutnya.

Satu hal yang perlu diperhatikan tentang kode ini adalah semua pemroses peristiwa ditambahkan ke window dan semuanya lulus {capture: true}. Ada beberapa alasan:

  • Tidak semua peristiwa Siklus Proses Halaman memiliki target yang sama. pagehide, dan pageshow diaktifkan pada window; visibilitychange, freeze, dan resume diaktifkan pada document, dan focus serta blur diaktifkan pada elemen DOM masing-masing.
  • Sebagian besar peristiwa ini tidak muncul sebagai balon, sehingga tidak mungkin untuk ditambahkan pemroses peristiwa non-capturing ke elemen ancestor umum dan mengamati semua tersebut lebih mendalam.
  • Fase pengambilan gambar dijalankan sebelum fase target atau balon, jadi menambahkan pemroses di sana memastikannya berjalan sebelum kode lain dapat membatalkannya.

Rekomendasi developer untuk setiap negara bagian

Sebagai developer, penting untuk memahami status Siklus Proses Halaman dan tahu cara mengamatinya dalam kode karena jenis pekerjaan yang harus Anda (dan harus tidak) sangat bergantung pada status halaman Anda.

Misalnya, tidak masuk akal untuk menampilkan notifikasi sementara kepada pengguna jika halaman dalam status tersembunyi. Meskipun contoh ini cukup jelas, ada rekomendasi lain yang tidak begitu jelas namun bernilai melakukan penghitungan.

Negara Bagian Rekomendasi developer
Active

Status aktif adalah waktu yang paling penting bagi pengguna sehingga waktu terpenting bagi halaman Anda untuk responsif terhadap input pengguna.

Semua pekerjaan non-UI yang dapat memblokir thread utama harus tidak diprioritaskan ke periode tidak ada aktivitas atau dialihkan ke pekerja web.

Passive

Dalam status pasif, pengguna tidak berinteraksi dengan halaman, tapi mereka masih bisa melihatnya. Ini berarti update UI dan animasi harus tetap berjalan lancar, tetapi waktu kapan pembaruan ini terjadi tidak terlalu penting.

Saat halaman berubah dari aktif menjadi pasif, hal ini adalah waktu yang tepat untuk mempertahankan status aplikasi yang belum disimpan.

Hidden

Saat halaman berubah dari pasif menjadi tersembunyi, halaman mungkin pengguna tidak akan berinteraksi dengan komputer itu lagi sampai dimuat ulang.

Transisi ke hidden juga sering kali merupakan perubahan status terakhir yang dapat diamati oleh pengembang (ini terutama berlaku pada seluler, karena pengguna dapat menutup tab atau aplikasi browser itu sendiri, dan beforeunload, pagehide, dan unload peristiwa tidak diaktifkan dalam kasus tersebut).

Ini berarti Anda harus memperlakukan status tersembunyi sebagai kemungkinan akhir dari sesi pengguna. Dengan kata lain, mempertahankan status aplikasi yang belum disimpan dan mengirim data analisis yang tidak terkirim.

Anda juga harus berhenti membuat pembaruan UI (karena pembaruan tersebut tidak akan terlihat oleh pengguna), dan Anda harus menghentikan tugas apa pun yang tidak diinginkan pengguna yang berjalan di latar belakang.

Frozen

Dalam status beku, tugas yang dapat dibekukan di task queue ditangguhkan hingga halaman dibekukan — yang mungkin tidak pernah terjadi (misalnya, jika halaman dihapus).

Hal ini berarti saat halaman berubah dari tersembunyi menjadi beku Anda harus menghentikan {i>timer<i} atau membongkar koneksi yang ada, jika dibekukan, dapat memengaruhi tab terbuka lain di asal yang sama, atau memengaruhi kemampuan browser untuk menempatkan laman dalam back-forward cache.

Secara khusus, Anda harus:

Anda juga harus mempertahankan status tampilan dinamis (misalnya, posisi scroll dalam tampilan daftar tak terbatas) untuk sessionStorage (atau pembaruan melalui commit()) yang ingin Anda pulihkan jika halaman telah dibuang dan dimuat ulang nanti.

Jika halaman bertransisi dari frozen kembali ke hidden, Anda dapat membuka kembali koneksi yang tertutup atau memulai ulang polling dihentikan saat halaman pertama kali dibekukan.

Terminated

Biasanya Anda tidak perlu melakukan tindakan apa pun saat halaman bertransisi ke status dihentikan.

Karena halaman yang dihapus muatannya sebagai akibat dari tindakan pengguna selalu melewati status hidden sebelum memasuki status dihentikan status hidden adalah status di mana logika akhir sesi (mis. mempertahankan status aplikasi dan pelaporan ke analisis) harus dilaksanakan.

Juga (seperti yang disebutkan dalam rekomendasi untuk status tersembunyi), sangat penting bagi developer untuk menyadari bahwa transisi ke status dihentikan tidak dapat dipercaya terdeteksi dalam banyak kasus (terutama di perangkat seluler), sehingga developer yang bergantung terkait peristiwa penghentian (mis. beforeunload, pagehide, dan unload) kemungkinan akan kehilangan data.

Discarded

Status dibuang tidak dapat diamati oleh developer di setiap kali halaman dihapus. Hal ini karena halaman biasanya dibuang karena keterbatasan resource, dan mencairkan halaman hanya untuk memungkinkan skrip untuk dijalankan sebagai respons terhadap kejadian {i>remove<i} sama sekali tidak mungkin dilakukan dalam dalam kebanyakan kasus.

Akibatnya, Anda harus bersiap untuk kemungkinan terjadinya {i>remove<i} perubahan dari hidden menjadi frozen, lalu Anda dapat bereaksi terhadap pemulihan halaman yang dibuang pada waktu pemuatan halaman dengan memeriksa document.wasDiscarded.

Sekali lagi, karena keandalan dan pengurutan peristiwa siklus proses diterapkan secara konsisten di semua browser, cara termudah untuk mengikuti saran pada tabel adalah dengan menggunakan PageLifecycle.js.

API siklus proses lama yang harus dihindari

Hal-hal berikut sebaiknya dihindari sebisa mungkin.

Peristiwa penghapusan muatan

Banyak developer memperlakukan peristiwa unload sebagai callback yang dijamin dan menggunakannya sebagai sinyal akhir sesi untuk menyimpan status dan mengirim data analisis, tetapi melakukan hal ini sangat tidak dapat diandalkan, terutama di perangkat seluler! Peristiwa unload tidak aktif dalam berbagai situasi penghapusan muatan yang biasa, termasuk menutup tab dari tab pengalih di perangkat seluler atau menutup aplikasi browser dari pengalih aplikasi.

Karena alasan ini, lebih baik untuk mengandalkan Peristiwa visibilitychange untuk menentukan waktu sesi berakhir, dan anggap status tersembunyi waktu terakhir yang dapat diandalkan untuk menyimpan data aplikasi dan pengguna.

Selain itu, keberadaan pengendali peristiwa unload terdaftar (melalui onunload atau addEventListener()) dapat mencegah browser dapat untuk menempatkan halaman dalam back/forward cache agar lebih cepat muatan mundur dan maju.

Dalam semua browser modern, disarankan untuk selalu menggunakan Peristiwa pagehide untuk mendeteksi kemungkinan penghapusan muatan halaman (alias status dihentikan), bukan peristiwa unload. Jika Anda mendukung Internet Explorer versi 10 dan yang lebih rendah, Anda harus menyertakan mendeteksi peristiwa pagehide dan hanya menggunakan unload jika browser tidak mendukung pagehide:

const terminationEvent = 'onpagehide' in self ? 'pagehide' : 'unload';

window.addEventListener(terminationEvent, (event) => {
  // Note: if the browser is able to cache the page, `event.persisted`
  // is `true`, and the state is frozen rather than terminated.
});

Peristiwa beforeunload

Peristiwa beforeunload memiliki masalah yang serupa dengan peristiwa unload. secara historis, keberadaan peristiwa beforeunload dapat mencegah halaman untuk memenuhi syarat untuk back/forward cache. Browser modern tidak memiliki batasan ini. Meskipun beberapa browser, sebagai tindakan pencegahan, tidak akan diaktifkan peristiwa beforeunload saat mencoba menempatkan halaman ke dalam mode back/forward {i>cache<i}, yang berarti bahwa peristiwa tersebut tidak dapat diandalkan sebagai sinyal akhir sesi. Selain itu, beberapa browser (termasuk Chrome) memerlukan interaksi pengguna di halaman sebelum mengizinkan peristiwa beforeunload terbakar, sehingga akan mempengaruhi keandalannya.

Satu perbedaan antara beforeunload dan unload adalah bahwa ada penggunaan yang sah atas beforeunload. Misalnya, ketika Anda ingin memperingatkan pengguna bahwa ada perubahan yang belum disimpan yang akan hilang jika mereka terus membongkar halaman.

Karena ada alasan yang valid untuk menggunakan beforeunload, sebaiknya Anda hanya menambahkan pemroses beforeunload saat pengguna memiliki perubahan yang belum disimpan, lalu menghapusnya segera setelah disimpan.

Dengan kata lain, jangan lakukan ini (karena akan menambahkan pemroses beforeunload tanpa syarat):

addEventListener('beforeunload', (event) => {
  // A function that returns `true` if the page has unsaved changes.
  if (pageHasUnsavedChanges()) {
    event.preventDefault();

    // Legacy support for older browsers.
    return (event.returnValue = true);
  }
});

Sebagai gantinya, lakukan ini (karena hanya menambahkan pemroses beforeunload saat diperlukan, dan menghapusnya jika tidak):

const beforeUnloadListener = (event) => {
  event.preventDefault();
  
  // Legacy support for older browsers.
  return (event.returnValue = true);
};

// A function that invokes a callback when the page has unsaved changes.
onPageHasUnsavedChanges(() => {
  addEventListener('beforeunload', beforeUnloadListener);
});

// A function that invokes a callback when the page's unsaved changes are resolved.
onAllChangesSaved(() => {
  removeEventListener('beforeunload', beforeUnloadListener);
});

FAQ

Mengapa tidak ada "memuat" negara bagian?

Page Lifecycle API mendefinisikan status menjadi diskret dan saling eksklusif. Karena suatu halaman dapat dimuat dalam status aktif, pasif, atau tersembunyi, dan karena dapat mengubah status—atau bahkan dihentikan—sebelum selesai dimuat, status pemuatan terpisah tidak masuk akal dalam paradigma ini.

Halaman saya berfungsi penting jika disembunyikan, bagaimana cara agar halaman tidak dibekukan atau dihapus?

Ada banyak alasan sah agar halaman web tidak dibekukan saat dijalankan dalam status tersembunyi. Contoh yang paling jelas adalah aplikasi yang memutar musik.

Ada situasi di mana Chrome akan berisiko menghapus sebuah halaman, seperti jika file berisi formulir dengan input pengguna yang belum dikirim, atau jika Pengendali beforeunload yang memperingatkan saat halaman menghapus muatan.

Untuk saat ini, Chrome akan bersikap konservatif saat membuang halaman dan lakukan hanya jika yakin bahwa hal tersebut tidak akan memengaruhi pengguna. Misalnya, halaman yang telah diamati untuk melakukan salah satu dari hal berikut sementara dalam status tersembunyi tidak akan dibuang kecuali dalam kendala sumber daya yang ekstrem:

  • Memutar audio
  • Menggunakan WebRTC
  • Memperbarui judul tabel atau favicon
  • Menampilkan peringatan
  • Mengirim notifikasi push

Untuk fitur daftar saat ini yang digunakan untuk menentukan apakah tab dapat aman dibekukan atau dibuang, lihat: Heuristik untuk Pembekuan & Menghapus di Chrome.

Apa itu back-forward cache?

Back/forward cache adalah istilah yang digunakan untuk menggambarkan pengoptimalan navigasi yang diterapkan beberapa browser, yang memanfaatkan tombol maju lebih cepat.

Saat pengguna keluar dari halaman, browser ini membekukan versi tersebut sehingga dapat dilanjutkan dengan cepat jika pengguna kembali menggunakan tombol kembali atau maju. Perlu diingat bahwa menambahkan unload pengendali peristiwa mencegah pengoptimalan ini.

Untuk semua maksud dan tujuan, pembekuan ini secara fungsional sama dengan browser yang membeku dilakukan untuk menghemat CPU/baterai; untuk alasan tersebut dianggap sebagai bagian dari status siklus proses yang dibekukan.

Jika saya tidak dapat menjalankan API asinkron dalam status terhenti atau dihentikan, bagaimana cara menyimpan data ke IndexedDB?

Dalam status dibekukan dan dihentikan, tugas yang dapat dibekukan di task queue halaman ditangguhkan, yang berarti API asinkron dan berbasis callback seperti tensorflow tidak dapat digunakan dengan andal.

Di masa mendatang, kita akan menambahkan metode commit() ke objek IDBTransaction, yang akan memberi pengembang cara untuk melakukan apa yang secara efektif merupakan transaksi hanya-tulis yang tidak memerlukan callback. Dengan kata lain, jika pengembang hanya menulis data kepada tensorflow dan tidak melakukan transaksi yang kompleks yang terdiri atas pembacaan dan penulisan, metode commit() dapat selesai sebelum task queue ditangguhkan (dengan asumsi database IndexedDB sudah terbuka).

Namun, untuk kode yang harus berfungsi saat ini, developer memiliki dua opsi:

  • Menggunakan Penyimpanan Sesi: Penyimpanan Sesi bersifat sinkron dan dipertahankan di seluruh penghapusan halaman.
  • Menggunakan IndexedDB dari pekerja layanan Anda: pekerja layanan dapat menyimpan data di AlarmManager setelah halaman dihentikan atau dihapus. Di freeze atau Dengan pemroses peristiwa pagehide, Anda dapat mengirim data ke pekerja layanan melalui postMessage(), dan pekerja layanan dapat menangani penyimpanan data.

Menguji aplikasi Anda dalam status dibekukan dan dihapus

Untuk menguji perilaku aplikasi Anda dalam status dibekukan dan dihapus, Anda dapat mengunjungi chrome://discards untuk benar-benar membekukan atau menghapus membuka tab.

Chrome Menghapus UI
Chrome Menghapus UI

Hal ini memungkinkan Anda memastikan halaman menangani freeze dan resume dengan benar peristiwa serta flag document.wasDiscarded saat halaman dimuat ulang dibuang.

Ringkasan

Developer yang ingin menghormati resource sistem perangkat pengguna mereka harus membangun aplikasi mereka dengan mempertimbangkan status Siklus Proses Halaman. Sangat penting untuk halaman web tidak memakai sumber daya sistem yang berlebihan dalam situasi yang yang tidak diharapkan pengguna

Makin banyak developer yang mulai mengimplementasikan Page Lifecycle API yang baru, makin aman API ini agar browser membeku dan menghapus halaman yang tidak digunakan. Ini berarti browser akan menggunakan lebih sedikit memori, CPU, baterai, dan sumber daya jaringan, yang menguntungkan pengguna.