JavaScript 权限 API 介绍
如果你曾经做过需要申请权限的应用(推送通知,访问摄像头,音频设备等),你可能注意到了,它们的 API 看起来不太一样。
// 对于定位 API ,需要调用 getCurrentPosition 来检查定位信息是否可用
navigator.geolocation.getCurrentPosition(gotLocation, didNotGetLocation);
// 对于消息通知,我们可以直接检查 Notification 对象
if (Notification.permission == 'granted')
// 授权后的逻辑
if (Notification.permission == 'denied')
// 请求授权
这显然不太方便。
权限 API 让我们可以查看页面上可用的权限。我们说的“权限”是指在代码里能否访问某个特性。需要用代码通过权限访问的特性称为“强力特性”。摄像头、音频设备接口(midi)、通知、地理位置等都是强力特性。
所有强力特性的 API 都有细微的差别。因此,要弄清楚每个特性的权限状态可能很麻烦。有了权限 API,我们可以通过单个接口管理所有权限的状态。
权限 API 基本概念
权限 API 目前还处于试验阶段,需要谨慎使用。只有在你能跟上破坏性的特性变化时才能在关键业务上使用它。例如,一些浏览器曾经支持 navigator.permissions.revoke ,但现在已经弃用了。
写这篇文章的时候, query是permissions接口里唯一可用的属性。query 接受一个叫做PermissionDescriptor的对象参数。该对象有个字段叫name,就是你要访问的权限名称。
// 该查询返回摄像头的权限信息
navigator.permissions.query({name: 'camera'});
查询返回一个 promise,resolve 结果是一个 PermissionStatus。它有两个字段:state 和 onchange。
navigator.permissions.query({name: 'camera'}).then( permissionStatus => {
console.log(permissionStatus);
// 我的浏览器控制台输出:
//{
// state: "prompt",
// onchange: null,
// }
})
state 有 3 个可能的值:granted,denied 和 prompt。granted 表示允许访问,denied表示不能访问,prompt表示浏览器在请求权限的时候弹出提示,询问用户。
有些 PermissionDescriptor 还有其他字段,你可以在这里查看更多。例如,camera的PermissionDescriptor还有一个额外的字段叫deviceId,用于指定某个摄像头。查询可能是这样:.query({name: 'camera', deviceId: "my-device-id"})。
onchange 是个事件监听器,当查询的权限变化时会被触发。
navigator.permissions.query({name:'camera'}).then(res => {
res.onchange = ((e)=>{
if (e.type === 'change'){
const newState = e.target.state
if (newState === 'denied') {
console.log('你怎么狠心拒绝我?')
} else if (newState === 'granted') {
console.log('在一起,不离不弃!')
} else {
console.log('让我们回到当初')
}
}
})
})
所有的权限 API
强力特性权限还有很多,并且浏览器支持情况不一。下面列出了W3C 编辑草案中描述的 permissionsName 变量包含的所有权限。getAllPermissions函数返回可用的权限数组及其状态。注意,这个结果会根据你的浏览器、用户设置和网站的设定而变化。
const permissionsNames = [
"geolocation",
"notifications",
"push",
"midi",
"camera",
"microphone",
"speaker",
"device-info",
"background-fetch",
"background-sync",
"bluetooth",
"persistent-storage",
"ambient-light-sensor",
"accelerometer",
"gyroscope",
"magnetometer",
"clipboard",
"display-capture",
"nfc"
];
const getAllPermissions = async () => {
const allPermissions = [];
await Promise.all(
permissionsNames.map(async permissionName => {
try {
let permission;
switch (permissionName) {
case 'push':
// 目前 Chrome 只支持用通知推送消息
permission = await navigator.permissions.query({name: permissionName, userVisibleOnly: true});
break;
default:
permission = await navigator.permissions.query({name: permissionName});
}
console.log(permission);
allPermissions.push({permissionName, state: permission.state});
}
catch(e){
allPermissions.push({permissionName, state: 'error', errorMessage: e.toString()});
}
})
)
return allPermissions;
}
在浏览器控制台执行:
(async function () {
const allPermissions = await getAllPermissions();
console.log(allPermissions);
})()
结果如下:
image.png
Worker 中的权限
到目前为止,我们只使用了 navigator.permissions API,因为用它写的例子更简单明了。权限 API 在 Worker 里同样可用,WorkerNavigator.permissions 即用于检查 Worker 内部的权限。
总结
本文简单介绍了 JavaScript 权限 API,希望能帮助你了解它的基本用法。它不复杂,也不是必需的,但如果你的网站要用到权限接口,用它来管理还是比较方便的。API 以后可能会有所变化,我会为你持续关注。
更多前端技术干货尽在微信公众号:1024译站
微信公众号:1024译站
发表评论 (审核通过后显示评论):