后台同步 是一个新的 Web API,允许您将操作推迟到用户达到稳定状态 连接。这样可确保用户想要发送的任何内容都能成功发送。
问题
互联网是一个浪费时间的地方。如果不在互联网上浪费时间,我们就不会知道猫不喜欢花、变色龙喜欢泡泡泡,也不会知道我们的埃里克·比德尔曼是90 年代末的推杆高尔夫大师。
但有时候,我们不想浪费时间。目标用户 更像是:
- 从口袋里拿出手机。
- 实现小目标。
- 将手机放回口袋。
- 恢复生命。
遗憾的是,连接不良经常会造成这种体验。我们都经历过。你凝视着白色屏幕或转动的图标,知道自己应该放弃,继续自己的生活,但为了以防万一,再给它 10 秒的时间。10 秒后?什么都不会发生。
可是为什么现在放弃呢?你已经投入了时间,什么都没带着就走了很浪费时间,所以你还等着呢。此时,您想要放弃,但您知道这样做的第二个,只有等待您等待,所有内容就会加载的第二个。
Service Worker 可让您通过缓存提供内容,从而解决网页加载部分的问题。但是,如果页面需要向服务器发送某些内容,该怎么办?
此时,如果用户点击“发送”他们必须盯着旋转图标,直到它完成为止。如果他们尝试离开或关闭该标签页,我们会使用 onbeforeunload
显示一条消息:“不,我需要您再凝视一下这个旋转图标。抱歉”。如果用户未连接到网络,我们会告诉用户“抱歉,您稍后必须返回并重试”。
这太垃圾了。后台同步功能可助您事半功倍。
解决方案
以下视频展示了仅包含表情符号的聊天演示 Emojoy。这是一款渐进式 Web 应用,支持离线优先运行。该应用使用推送消息和通知,并使用后台同步。
如果用户在没有网络连接时尝试发送消息,所幸的是,消息会在用户连接到网络后在后台发送。
自 2016 年 3 月起,Chrome 49 及更高版本均提供后台同步功能。您可以按照以下步骤查看操作:
- 打开 Emojoy。
- 离线(使用飞行模式或前往您当地的法拉第笼子)。
- 输入消息。
- 返回主屏幕(可以选择关闭标签页或浏览器)。
- 连接到网络。
- 在后台发送消息!
能够像这样在后台发送也可以带来可察觉的性能提升。应用不需要过多处理消息发送,因此可以直接将消息添加到输出中。
如何请求后台同步
在真正的可扩展网页样式中, 一种底层功能,可让您自由执行所需的操作。您请求 该事件会在用户连接时立即触发,如果用户 已经连接。然后,您可以监听该事件 所需执行的操作。
与推送消息传递一样,它使用 Service Worker 作为事件目标,使其在页面未打开时能够工作。首先,请从网页注册同步:
// Register your service worker:
navigator.serviceWorker.register('/sw.js');
// Then later, request a one-off sync:
navigator.serviceWorker.ready.then(function(swRegistration) {
return swRegistration.sync.register('myFirstSync');
});
```
Then listen for the event in `/sw.js`:
```js
self.addEventListener('sync', function(event) {
if (event.tag == 'myFirstSync') {
event.waitUntil(doSomeStuff());
}
});
这样就大功告成了!在上文中,doSomeStuff()
应返回一个 promise,表明它尝试执行的任何操作是否成功。如果满足,则同步完成。如果失败,系统会安排另一次同步重试。重试同步也会等待连接,并采用指数退避算法。
对于给定的同步,同步的标记名称(上例中的 myFirstSync)应是唯一的。如果您使用与待处理同步相同的标记来注册同步,则该标记将与现有同步合并。也就是说,您可以申请“发件箱”同步。但是,如果他们离线时发送了 5 封邮件,则您只会在其恢复在线状态时获得一次同步。如果您需要 5 个单独的同步事件,只需使用唯一标记即可!
这里给出了最基本的演示内容:它使用同步事件来显示通知。
后台同步有哪些用途?
理想情况下,您可以使用它来安排在页面生命周期之外发送您关注的任何数据。聊天消息、电子邮件、文档更新、设置更改、照片上传...任何你想要到达服务器的内容,即使用户离开或关闭标签页也是如此。网页可以将这些内容存储在“发件箱”中存储在 indexDB 中,然后 Service Worker 会检索并发送它们。
不过,您也可以使用它来提取少量数据...
另一个演示!
这是我为推动网页加载而制作的离线维基百科演示。后来,我还为它添加了一些后台同步魔法。
亲自尝试一下吧。请确保您使用的是 Chrome 49 及更高版本,然后执行以下操作:
- 转到任意文章(例如 Chrome)。
- 离线(使用飞行模式,或加入像我这样糟糕的移动服务提供商)。
- 点击指向其他文章的链接。
- 系统应告知您页面加载失败(如果页面加载时间较短,系统也会显示此消息)。
- 同意接收通知。
- 关闭浏览器。
- 切换为在线状态
- 当文章下载、缓存和可供查看时,您会收到通知!
通过使用该模式,用户可以将手机放在口袋里,继续自己的生活,因为知道当手机被拿到他们需要时,手机会提醒他们。
权限
我展示的演示使用网络通知,此类通知需要权限,但后台同步本身不需要。
通常,同步事件会在用户已打开网站页面时完成,因此需要用户许可会给他们带来糟糕的体验。而是会限制何时可以注册和触发同步,以防止滥用行为。例如:
- 您只能在用户打开网站的窗口时注册同步事件。
- 事件执行时间是有上限的,所以您不能每 x 秒对服务器执行一次 ping 操作、进行比特币挖矿或其他任何活动。
当然,这些限制可能会因实际使用情况而放宽或收紧。
采用渐进增强的方式
需要一段时间,所有浏览器都支持后台同步,特别是 Safari 和 Edge 尚不支持 Service Worker。不过,渐进式增强有助于实现这一目的:
if ('serviceWorker' in navigator && 'SyncManager' in window) {
navigator.serviceWorker.ready.then(function(reg) {
return reg.sync.register('tag-name');
}).catch(function() {
// system was unable to register for a sync,
// this could be an OS-level restriction
postDataFromThePage();
});
} else {
// serviceworker/sync not supported
postDataFromThePage();
}
如果 Service Worker 或后台同步功能不可用,则只需发布内容 从这个网页中复制代码。
即使用户看起来连接状况良好,您也可以使用后台同步功能,因为这可以防止在数据发送期间导航和标签页关闭。
未来展望
我们的目标是在 2016 年上半年将后台同步功能发送到稳定版 Chrome 中,同时开发“定期后台同步”变体。通过定期后台同步,您可以请求受时间间隔、电池状态和网络状态限制的事件。当然,这需要获得用户许可,而且这些事件的触发时间和频率也由浏览器决定。换言之,某个新闻网站可能每小时请求同步一次,但浏览器可能知道您是在 07:00 才阅读该网站,因此系统每天 06:50 都会触发同步。这种想法比一次性同步稍微复杂一点,但它即将推出。
我们正在逐步将 Android 和 iOS 中的成功模式引入 Web,同时仍然保留让 Web 变得出色的功能!