Web编程技术营地
研究、演示、创新

Caches

撰写时间:2024-12-25

修订时间:2025-08-25

概述

CachesHTML 5中所定义的一种在浏览器中建立起缓存的工作机制。

navigator

常见属性

window有一个navigator对象,下面打印该对象,以及该对象下一些常见的属性名值。

pc.log(navigator); ['cookieEnabled', 'userAgent', 'vendor', 'platform'] .forEach(propName => { pc.log('%s: %s', propName, navigator[propName]); });

Chrome的navigator对象的属性数量比Safari的属性数量要多得多。

userAgent是用户所使用的浏览器信息。根据Infra Living Standard的定义,user agent用户代理)是指在用户访问网络时能代表用户身份的特定应用软件。通常指代浏览器。但浏览器允许切换用户代理的身份。例如,在Safari浏览器中,点击菜单开发 -> 用户代理,则可以自由地切换到其他身份。假设切换到Goole Chrome - Windows,则userAgent属性值就能反映出这种变化。

platform是用户操作系统的名称。Mac电脑有两种,一种是基于 Silicon 芯片,另一种是基于 Intel 芯片。当笔者使用 Mac 电脑来访问本页时,将显示MacIntel,表明该电脑的芯片类型为Intel

Permissions

在使用手机上的Apps时,有些Apps可能会弹出一些要求获得相应权限的的询问,如:是否允许本App使用您手机的摄像头是否允许访问您的本地相册是否允许向您发送通知?,等等。如果用户同意,则这些Apps就能提供功能强大的特性 (powerful feature)。

网页应用也同样存在类似问题。

navigator对象的permissions属性值,返回一个Permissions对象实例。

pc.log(navigator.permissions);

该对象只有一个query方法,用以查询是否具备使用相应功能强大的特性的权限。

下面查看各浏览器支持的情况。

let names = ['geolocation', 'notifications', 'push', 'web-share', 'accelerometer', 'window-management', 'local-fonts']; let promises = names.map(name => navigator.permissions.query({ name })); let supported = []; let unsupported = []; let index = 0; await Promise.allSettled(promises) // allSettled() raises no errors .then(promiseStatuses => { for (let promiseStatus of promiseStatuses) { // {status: 'fulfilled' or 'rejected', value or reason} if (promiseStatus.status === 'fulfilled') { let permissionStatus = promiseStatus.value; const {name, state} = permissionStatus; supported.push(`name: ${name}; state: ${state}`); } else if (promiseStatus.status === 'rejected') { unsupported.push(`name: '${names[index]}'; reason: '${promiseStatus.reason.message}'`); } index++; } }); pc.group('Supported'); supported.forEach(msg => { pc.log('%s', msg); }); pc.groupEnd(); pc.group('Unsupported'); unsupported.forEach(msg => { pc.log('%s', msg); }); pc.groupEnd();

在Web平台,geolocation, notifications, push, web-share4个是标准化的特性。尽管如此,各浏览器支持力度也不一样。例如,Safari目前不支持web-share特性。

而各浏览器也自带一些支持的特性,下面是Safari所支持的特性:

enum PermissionName { // FIXME: update the list to match spec when new features are implemented. "accelerometer", "background-fetch", "bluetooth", "camera", "display-capture", "geolocation", "gyroscope", "magnetometer", "microphone", "midi", "nfc", "notifications", "push", "screen-wake-lock", "speaker-selection", "storage-access" };

变量permissionStatusstate属性值只有3种:"denied", "granted""prompt",分别代表拒绝已授权可通过提示框来授权的意思。

storage

navigator对象的storage属性值,返回一个StorageManager对象实例,可用来管理用户在浏览器存储相应数据的权限,以及获取存储容量。

pc.log(navigator.storage); navigator.storage.persisted() .then(persistent => { pc.log(persistent); }); navigator.storage.persist() .then(persistent => { pc.log(persistent); }); navigator.storage.estimate() .then(estimate => { pc.log(estimate); pc.log(`quatoa: ${(estimate.quota / 1024 / 1024).toFixed(2)}MB`, ); pc.log(`usage: ${(estimate.usage / 1024 / 1024).toFixed(2)}MB`, ); pc.log(`usage percent: ${(estimate.usage / estimate.quota).toFixed(6)}%`, ); });

Indexed DB, Cache API, Service Worker,localStorage, sessionStorage, application caches, notifications,均属于storage管理范围之列。

全局对象caches

在Web环境中,window有一个名为caches的属性,即是用以建立缓存的对象。

pc.log(caches);

caches的类型为CacheStorage,只有match, has, open, delete, 及keys等少数几个方法。

查看caches所有键名

通过调用cacheskeys方法,可以查看所有的键名。

caches.keys() .then(keys => pc.log(keys));

因为caches是在浏览器的本地存储上建立的一种存储机制,因此,对于每个浏览器来讲,它是全局性的。如果之前我们曾使用过caches来存储特定数据,则上面的代码会将所使用过的键名都显示出来。

删除caches所有键

因为caches是全局性的对象,为避免受之前的影响,在这里,我们希望删除之前所有曾经使用过的键。

await caches.keys() .then(keys => { keys.forEach(keyName => { pc.log(keyName); caches.delete(keyName); }); })

因本站已在本目录上建立起了Service worker,以及受到下面各节代码的影响,当上面代码运行后,每刷新网页2次,都会看到相关的键名又会自动冒出来。

新建或打开键

可以调用cachesopen方法来打开一个键,此时将返回一个类型为Cache的对象。如果要打开的键名不存在,则先创建一个键再打开。

caches.open('shell-v1') .then(cache => { pc.log(cache); return cache.keys(); }) .then(requests => { requests.forEach((request) => { pc.log(request.url); }); })

特定键名的Cache对象,其各个方法与caches比较相像,但其keys方法返回的不再是字符串,而是Request对象。

添加键值

caches.open("temp-v1") .then(cache => { let resources = [ 'index.php' ]; cache.addAll(resources); return cache.keys(); }) .then(requests => { requests.forEach((request) => { pc.log(request.url); }); });

addaddAll方法将导致在内部通过调用fetch函数加载后,再将返回的Responses添加进缓存中。

这就是Caches的本质,它的键名是Request对象,键值是Response对象,即将指定网页地址的网页内容保存进缓冲区,当用户访问这些缓冲区中的内容时,可直接从缓冲区中读取,即使没有网络连接。

参考资源

Specifications

  1. Storage endpoints
  2. Infra Living Standard: user-agent
  3. Permissions

Webkit

  1. Webkit PermissionName

MDN

  1. Cache
  2. Permissions: query() method