如果你曾经创建了一个需要不同的功能的Web应用程序(如推送通知、网络摄像头访问、midi访问),你可能会注意到他们的API看起来非常不同。
1// for the geolocation API you need to call getCurrentPosition to check if geolocation is accessible
2navigator.geolocation.getCurrentPosition(gotLocation, didNotGetLocation);
3
4// for notifications we can directly check on the Notification object
5
6if (Notification.permission == 'granted')
7 // do notification stuff
8if (Notification.permission == 'denied')
9 // ask for notification access ....
这不是很方便的。
Permissions API允许我们对在我们的页面上可用的权限进行概述。我们用允许
的意思是我们是否可以使用我们的代码访问特定功能。需要允许使用代码访问的功能称为强大的功能。
所有强大的功能的 API 都略有不同,因此,了解每个功能的权限状态可能很痛苦。
基本的 API 许可
允许API在这个阶段是非常实验性的,应该仔细使用。你只应该使用它,如果它是关键的任务,你可以跟上未来的破坏变化。例如,一些浏览器曾支持‘navigator.permissions.revoke’,但它现在已经过期。
在写作时,查询
是我们可以从允许
接口访问的唯一属性。查询
作为一个称为 PermissionDescriptor的论点,使用一个对象。
1// This query will give us information about the permissions attached to the camera
2navigator.permissions.query({name: 'camera'})
该查询返回一个承诺,解决为PermissionStatus
。PermissionStatus有两个字段:状态
和变更
。
1navigator.permissions.query({name: 'camera'}).then( permissionStatus => {
2 console.log(permissionStatus)
3 // in my browser on this page it logs:
4 //{
5 // status: "prompt",
6 // onchange: null,
7 // }
8})
状态
有3种可能的状态:授予
,拒绝
和提示
。授予
意味着我们可以访问该功能,拒绝
意味着我们无法访问该功能,提示
意味着用户代理(即浏览器)将要求用户允许我们尝试访问该功能。
有些PermissionDescriptor
有额外的字段,例如camera’s PermissionDescriptor
有一个额外的字段,名为deviceId
,如果您想瞄准特定摄像头,则您的查询可能看起来像: `.query({name: 'camera', deviceId: "my-device-id"})」。
「變更」是一個事件聆聽器,每當被查詢的功能的權限變更時,就會啟用。
1navigator.permissions.query({name:'camera'}).then(res => {
2 res.onchange = ((e)=>{
3 // detecting if the event is a change
4 if (e.type === 'change'){
5 // checking what the new permissionStatus state is
6 const newState = e.target.state
7 if (newState === 'denied') {
8 console.log('why did you decide to block us?')
9 } else if (newState === 'granted') {
10 console.log('We will be together forever!')
11 } else {
12 console.log('Thanks for reverting things back to normal')
13 }
14 }
15 })
16})
所有 API 许可
有许多不同的强大的权限和浏览器支持是非常不均匀的。在下面的脚本中,你可以看到所有由W3C编辑的草案描述的权限(https://w3c.github.io/permissions/#permission-registry)在permissionsName
变量中。getAllPermissions
函数返回了各种可用的权限和他们的状态。请注意,结果将取决于您的浏览器,用户的偏好和网站的设置。
1const permissionsNames = [
2 "geolocation",
3 "notifications",
4 "push",
5 "midi",
6 "camera",
7 "microphone",
8 "speaker",
9 "device-info",
10 "background-fetch",
11 "background-sync",
12 "bluetooth",
13 "persistent-storage",
14 "ambient-light-sensor",
15 "accelerometer",
16 "gyroscope",
17 "magnetometer",
18 "clipboard",
19 "display-capture",
20 "nfc"
21]
22
23const getAllPermissions = async () => {
24 const allPermissions = []
25 // We use Promise.all to wait until all the permission queries are resolved
26 await Promise.all(
27 permissionsNames.map(async permissionName => {
28 try {
29 let permission
30 switch (permissionName) {
31 case 'push':
32 // Not necessary but right now Chrome only supports push messages with notifications
33 permission = await navigator.permissions.query({name: permissionName, userVisibleOnly: true})
34 break
35 default:
36 permission = await navigator.permissions.query({name: permissionName})
37 }
38 console.log(permission)
39 allPermissions.push({permissionName, state: permission.state})
40 }
41 catch(e){
42 allPermissions.push({permissionName, state: 'error', errorMessage: e.toString()})
43 }
44 })
45 )
46 return allPermissions
47}
如果我在Alligator.io上的开发者控制台中运行以下代码:
1(async function () {
2 const allPermissions = await getAllPermissions()
3 console.log(allPermissions)
4})()
以下是我在控制台上得到的屏幕截图:
工人许可证
到目前为止,我们只使用navigator.permissions
API,因为编写简要的示例要容易得多。
希望您现在能够更好地了解如何使用 Permissions API. 它并不复杂,也不是必不可少的,但它确实使我们更容易在基于JavaScript的应用程序中管理权限。