请求权限的麻烦……
Web 上的权限是必要的恶,但作为开发者处理起来并不有趣。
历史上,不同的 API 以不一致的方式处理其自身的权限——例如,Notifications API 有自己检查权限状态和请求权限的方法,而 Geolocation API 则没有。
Permissions API 为开发者提供了一种一致的方法,并允许他们在权限方面实现更好的用户体验。具体来说,开发者可以使用 Permissions.query() 来检查当前上下文中是否已授予、拒绝或需要通过提示来授予使用特定 API 的权限。在主线程中查询权限 广泛支持,在 Worker 中也支持(有一个例外)。
许多 API 现在支持权限查询,例如 Clipboard API、Notifications API、Push API 和 Web MIDI API。在 API 概述 中提供了许多支持权限的 API 的列表,您可以在 此处兼容性表 中了解浏览器支持情况。
Permissions 还有其他方法可以专门请求使用 API 的权限以及撤销权限,但这些方法已弃用(非标准,和/或不支持)。
一个简单的例子
对于本文档,我们构建了一个名为 Location Finder 的简单演示。它使用 Geolocation 来查询用户的当前位置并将其显示在 Google 地图上。

您可以 在线运行示例,或 在 GitHub 上查看源代码。大部分代码都很简单且普通——下面我们只介绍与 Permissions API 相关的代码,如果您想研究其他部分,请自行查看代码。
访问 Permissions API
浏览器已添加 Navigator.permissions 属性以允许访问全局 Permissions 对象。该对象最终将包含查询、请求和撤销权限的方法,尽管目前它只包含 Permissions.query();请参见下文。
查询权限状态
在我们的示例中,Permissions 功能由一个函数——handlePermission()——处理。该函数首先使用 Permissions.query() 查询权限状态。根据 promise 解析时返回的 PermissionStatus 对象的 state 属性的值,它会做出不同的响应。
"granted"-
“Enable Geolocation”按钮被隐藏,因为如果 Geolocation 已激活则不需要它。
"prompt"-
“Enable Geolocation”按钮被隐藏,因为如果用户将被提示授予 Geolocation 权限,则不需要它。然后运行
Geolocation.getCurrentPosition()函数,该函数会提示用户授予权限;如果授予权限(显示地图),则运行revealPosition()函数,或者如果拒绝权限(显示“Enable Geolocation”按钮),则运行positionDenied()函数。 "denied"-
“Enable Geolocation”按钮被显示(此代码也必须在此处,以防页面首次加载时该原点的权限状态已设置为 denied)。
function handlePermission() {
navigator.permissions.query({ name: "geolocation" }).then((result) => {
if (result.state === "granted") {
report(result.state);
geoBtn.style.display = "none";
} else if (result.state === "prompt") {
report(result.state);
geoBtn.style.display = "none";
navigator.geolocation.getCurrentPosition(
revealPosition,
positionDenied,
geoSettings,
);
} else if (result.state === "denied") {
report(result.state);
geoBtn.style.display = "inline";
}
result.addEventListener("change", () => {
report(result.state);
});
});
}
function report(state) {
console.log(`Permission ${state}`);
}
handlePermission();
权限描述符
Permissions.query() 方法接受一个 PermissionDescriptor 字典作为参数——其中包含您感兴趣的 API 的名称。某些 API 具有更复杂的 PermissionDescriptor,包含附加信息,这些信息继承自默认的 PermissionDescriptor。例如,PushPermissionDescriptor 还应包含一个布尔值,指定 userVisibleOnly 是 true 还是 false。
响应权限状态更改
您会注意到我们在上面的代码中正在监听附加到 PermissionStatus 对象上的 change 事件——这允许我们响应我们感兴趣的 API 的权限状态的任何更改。目前我们只是报告状态的变化。