[译] 使用 Page Visibility API,保存和恢复程序状态

396 阅读3分钟

原文链接:Don't lose user and app state, use Page Visibility,by Ilya Grigorik

好的程序不会丢失用户进度和程序状态。它们可以在不打扰用户的前提下,自动保存一些必要数据,并在需要时恢复——比如,从后台状态或意外关机后恢复。

不幸的是,很多 Web 程序因为没有考虑移动端生命周期而出错:它们监听的事件可能从不会被触发,或用完全糟糕的用户体验为代价忽略这个问题。公平地说,Web 平台也因为暴露太多事件让这一过程更加简化:visibilityStatepageshowpagehidebeforeunloadunload。应该用哪一个,什么时候用呢?

你不能在移动端依赖 pagehidebeforeunloadunload 事件。这不是浏览器的 bug,而是因为不同移动操作系统的工作方式是有区别的。一个“前台程序(active application)”可以通过下面几种方式进入到“后台状态(background state)”:

  • 用户通过点击通知(notification)切换到另一个 App。
  • 用户通过任务切换器(task switcher)切换到另一个 App。
  • 用户通过点击 Home 键进入主屏(homescreen)。
  • 操作系统可以代表用户切换到另一个 App——比如有来电时。

一旦程序过渡到后台状态,它就可能会在没有任何征兆的情况下被杀死。例如,操作系统可能会为了回收资源而终止进程、用户可以在任务管理器中滑动退出应用程序。这些情况下,你以为会触发页面的 pagehidebeforeunloadunload 事件,然后程序就“彻底关闭”了,但实际是基本不会触发。

为了在桌面和移动端上提供可靠且一致的用户体验,应用程序必须使用 Page Visibility API ,在每次 visibleChange事件触发导致状态改变时,执行会话保存和逻辑恢复的任务。这是你的程序可以依靠的唯一事件。

// query current page visibility state: prerender, visible, hidden
var pageVisibility = document.visibilityState;

// subscribe to visibility change events
document.addEventListener('visibilitychange', function() {
  // fires when user switches tabs, apps, goes to homescreen, etc.
	if (document.visibilityState == 'hidden') { ... }

	// fires when app transitions from prerender, user returns to the app / tab.
	if (document.visibilityState == 'visible') { ... }
});

如果您要依靠 unload 来保存状态、记录和报告分析数据或者执行其他相关逻辑,那么将会丢失很大一部分的移动会话数据,因为 unload 事件不会触发,使用 beforeunload 事件来提示用户有未保存的数据做法于此一样,都会因为在移动端不会触发这个事件而导致问题。

使用 Page Visibility API 并忘记其他事件。将每次到 visible 的过渡视为一个新的会话:还原以前的状态、重置分析系统等等。 然后,当应用程序过渡到 hidden 状态时,结束会话:保存用户和应用程序状态、使用 Beacon API 发送分析数据,或执行所有其他的必要工作。

兼容性

从长远来看,你只要使用 Page Visibility API 就够了。下面是我 手工测试 的,上面讲过的事件在不同设备中的支持情况:

  • visibilityChange 在移动端进行任务切换时表现的很好。
  • beforeunload 的价值就比较有限,仅在桌面端触发。
  • unload 事件则在移动和桌面端 Safair 浏览器上都不受支持。

(正文完)


广告时间(长期有效)

我有一位好朋友开了一间猫舍,在此帮她宣传一下。现在猫舍里养的都是布偶猫。如果你也是个爱猫人士并且有需要的话,不妨扫一扫她的【闲鱼】二维码。不买也不要紧,看看也行。

(完)