什么是 PWA?
PWA(Progressive Web App)是一种新型的 Web 应用程序模型,它不仅具备传统 Web 应用的优点,例如可访问性、可搜索性以及与其他 Web 应用的链接性等,同时还具备接近原生应用的许多特性,例如离线支持、消息推送、硬件访问等。
PWA 中的离线支持
离线支持是 PWA 最为重要的特性之一,它能够保证应用程序可以在没有网络连接的情况下运行。在 PWA 中,离线支持主要由以下两个技术实现:
- Service Worker:一种运行在浏览器后台的 JavaScript 脚本,能够拦截所有的网络请求,从而实现请求的离线缓存和自定义响应。
- IndexedDB:一种近似原生数据库的 Web API,允许 Web 应用程序在客户端存储结构化数据,同时提供强大的查询和索引功能。
本文将主要介绍如何使用 IndexedDB 存储离线数据,从而实现 PWA 中的离线支持。
IndexedDB 简介
IndexedDB 是一种在客户端存储结构化数据的 Web API,它与传统的关系型数据库非常相似,但更加轻量级、灵活和易于使用。下面是一些 IndexedDB 的特点:
- 客户端存储:IndexedDB 在客户端存储数据,不需要像传统的 Web 应用一样依赖于服务器端。这样可以减少网络延迟、提高应用性能,并且增强了应用程序的离线支持。
- 面向对象:IndexedDB 以对象存储为核心,每一个对象存储都包含若干个对象,每个对象又包含若干个属性。这种面向对象的设计可以更好地适应客户端的存储需求。
- 索引查询:IndexedDB 支持创建索引,从而可以更快地查询数据。同时,IndexedDB 还提供了灵活的查询语言和事务机制,可以满足更多的查询需求。
IndexedDB 基本操作
IndexedDB 的核心操作主要包括以下几个步骤:
- 打开一个数据库。
- 创建一个对象存储。
- 向对象存储中添加数据。
- 从对象存储中查询数据。
下面是一些 IndexedDB 基本 API 的使用示例:
// javascriptcn.com 代码示例 // 打开一个数据库 const request = indexedDB.open('myDatabase', 1); // 创建一个对象存储 request.onupgradeneeded = function(event) { const db = event.target.result; const objectStore = db.createObjectStore('customers', { keyPath: 'id' }); objectStore.createIndex('name', 'name', { unique: false }); }; // 向对象存储中添加数据 request.onsuccess = function(event) { const db = event.target.result; const transaction = db.transaction(['customers'], 'readwrite'); const objectStore = transaction.objectStore('customers'); const customer = { id: 12345, name: 'John Doe', email: 'john@example.com' }; const request = objectStore.add(customer); request.onsuccess = function(event) { console.log('Customer added'); }; }; // 从对象存储中查询数据 request.onsuccess = function(event) { const db = event.target.result; const transaction = db.transaction(['customers'], 'readonly'); const objectStore = transaction.objectStore('customers'); const request = objectStore.get(12345); request.onsuccess = function(event) { console.log(request.result); }; };
在 PWA 中使用 IndexedDB 存储离线数据
在 PWA 中,我们可以使用 IndexedDB 存储离线数据,从而实现应用程序的离线支持。下面是一个 IndexedDB 存储离线数据的示例:
// javascriptcn.com 代码示例 if ('serviceWorker' in navigator) { // 注册 Service Worker navigator.serviceWorker.register('/sw.js'); // 打开一个 IndexedDB 数据库 const request = indexedDB.open('offlineData', 1); // 创建一个对象存储 request.onupgradeneeded = function(event) { const db = event.target.result; db.createObjectStore('offlineRequests', { keyPath: 'id', autoIncrement: true }); }; // 在离线状态下,将请求保存到 IndexedDB 中 const saveRequest = function(request) { const db = request.result; const transaction = db.transaction(['offlineRequests'], 'readwrite'); const objectStore = transaction.objectStore('offlineRequests'); objectStore.add(request.clone()); }; // 在离线状态下,从 IndexedDB 中读取请求并重新发送 const resendRequests = function() { const db = request.result; const transaction = db.transaction(['offlineRequests'], 'readwrite'); const objectStore = transaction.objectStore('offlineRequests'); const requests = objectStore.getAll(); requests.onsuccess = function(event) { const data = requests.result; data.forEach(function(request) { fetch(request.url, { method: request.method, headers: request.headers, body: request.body, mode: 'no-cors', redirect: 'follow', }).then(function(response) { if (response.status === 200 || response.status === 0) { objectStore.delete(request.id); } }); }); }; }; // 监听 fetch 事件,实现离线支持 self.addEventListener('fetch', function(event) { if (!navigator.onLine && event.request.method === 'POST') { event.respondWith( new Response('', { status: 408, statusText: 'Request Timeout', }) ); saveRequest(event.request); } else { event.respondWith( fetch(event.request).catch(function() { return new Response('<h1>Offline Mode</h1>', { headers: { 'Content-Type': 'text/html' }, }); }) ); } }); // 监听 online 事件,重新发送离线请求 self.addEventListener('online', function() { resendRequests(); }); // 在页面加载时,从 IndexedDB 中重新发送离线请求 window.addEventListener('load', function() { resendRequests(); }); }
上述示例中,我们首先打开一个 IndexedDB 数据库,并创建一个对象存储。然后,在离线状态下,我们将请求保存到 IndexedDB 中。在在线状态下,我们使用 Service Worker 拦截所有的 fetch 请求,如果请求失败,则返回一个示意的离线界面,并将请求保存到 IndexedDB 中。在 online 事件触发时,我们重新发送离线请求。
总结
本文介绍了 PWA 中的离线支持,重点介绍了 IndexedDB 存储离线数据的使用方法。如果你想在自己的 Web 应用中使用 PWA 技术,那么 IndexedDB 作为一个非常重要的技术点,一定需要认真掌握和使用。
来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/6546118b7d4982a6ebfd91c2