使用 Permissions API

本文档提供了一个使用 Permissions API 的基础指南,该 API 提供了一种以编程方式查询当前上下文的 API 权限状态的方法。

请求权限的麻烦……

Web 上的权限是必要的恶,但作为开发者处理起来并不有趣。

历史上,不同的 API 以不一致的方式处理其自身的权限——例如,Notifications API 有自己检查权限状态和请求权限的方法,而 Geolocation API 则没有。

Permissions API 为开发者提供了一种一致的方法,并允许他们在权限方面实现更好的用户体验。具体来说,开发者可以使用 Permissions.query() 来检查当前上下文中是否已授予、拒绝或需要通过提示来授予使用特定 API 的权限。在主线程中查询权限 广泛支持,在 Worker 中也支持(有一个例外)。

许多 API 现在支持权限查询,例如 Clipboard APINotifications APIPush APIWeb MIDI API。在 API 概述 中提供了许多支持权限的 API 的列表,您可以在 此处兼容性表 中了解浏览器支持情况。

Permissions 还有其他方法可以专门请求使用 API 的权限以及撤销权限,但这些方法已弃用(非标准,和/或不支持)。

一个简单的例子

对于本文档,我们构建了一个名为 Location Finder 的简单演示。它使用 Geolocation 来查询用户的当前位置并将其显示在 Google 地图上。

Screenshot showing a map of Greenfield, UK.

您可以 在线运行示例,或 在 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)。

js
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 还应包含一个布尔值,指定 userVisibleOnlytrue 还是 false

响应权限状态更改

您会注意到我们在上面的代码中正在监听附加到 PermissionStatus 对象上的 change 事件——这允许我们响应我们感兴趣的 API 的权限状态的任何更改。目前我们只是报告状态的变化。