Javascript WebUSB:如果navigator.usb.getDevices()失败,如何调用navigator.usb.requestDevice()

Javascript WebUSB:如果navigator.usb.getDevices()失败,如何调用navigator.usb.requestDevice(),javascript,promise,usb,webusb,Javascript,Promise,Usb,Webusb,我正在为Scratch3编写一个基于WebUSB的扩展。在extensions构造函数中,我需要建立WebUSB连接。理想情况下,我希望使用navigator.usb.getDevices()检查可用/配对的设备,如果失败,我希望让用户使用navigator.usb.requestDevice()选择一个设备 问题是需要从用户手势调用navigator.usb.requestDevice()。在大多数情况下,scratch3扩展构造函数是从用户操作调用的,因此我可以很好地使用navigator.

我正在为Scratch3编写一个基于WebUSB的扩展。在extensions构造函数中,我需要建立WebUSB连接。理想情况下,我希望使用navigator.usb.getDevices()检查可用/配对的设备,如果失败,我希望让用户使用navigator.usb.requestDevice()选择一个设备

问题是需要从用户手势调用navigator.usb.requestDevice()。在大多数情况下,scratch3扩展构造函数是从用户操作调用的,因此我可以很好地使用navigator.usb.requestDevice()

但是navigator.usb.getDevices()返回一个承诺,并从那里调用navigator.usb.requestDevice()失败 “必须处理用户手势才能显示权限请求。”

因此,以下方法可行(但每次都会打开一个请求对话框):

但由于缺少“用户手势”,以下操作失败:

我希望避免弄乱Scratch3核心,因此不想添加另一个UI元素

在第一个代码段中仅使用navigator.usb.requestDevice()有两个主要缺点:

  • 它会一直打开请求对话框,尽管只需要打开一次
  • 有时,稍后可能会在非交互情况下调用构造函数,navigator.usb.requestDevice()将完全失败,而navigator.usb.getDevices()将成功

  • 有没有办法让第二个代码段的方法起作用?

    我不熟悉Scratch 3,但在初始化扩展时是否可以调用
    getDevices()
    ,并延迟提供一个按钮,用户可以单击该按钮触发
    requestDevice()
    直到代码知道它是否已经拥有访问设备的权限之后


    提供了
    getDevices()
    方法和
    onconnect
    ondisconnect
    事件处理程序,以便页面可以使其界面与任何可用设备保持最新状态。

    我不熟悉Scratch 3,但是否可以调用
    getDevices()
    当您的扩展被初始化并延迟提供按钮时,用户可以单击按钮触发
    requestDevice()
    ,直到代码知道它是否已经拥有访问设备的权限为止


    getDevices()
    方法,提供了
    onconnect
    ondisconnect
    事件处理程序,以便页面能够与任何可用设备保持最新的界面。

    这一点从Chrome 72开始就通过该功能得到了修复。

    这一点从Chrome 72开始就通过该功能得到了修复。

    正如我所写的:
    我希望避免与Scratch 3 core,因此不想添加另一个UI元素。
    搞乱UI和/或core基本上消除了使用常规Scratch 3版本运行扩展的机会。正如我所写:
    我希望避免搞乱Scratch 3 core,因此不想添加另一个UI元素。
    搞乱UI和/或核心基本上消除了使用常规scratch3版本运行扩展的可能性。
    navigator.usb.requestDevice({ filters: [{ vendorId: 0x2341 }] })
            .then(selectedDevice => {
                // ...
            })
    
    navigator.usb.getDevices().then(devices => {
        if(devices.length == 0) {
            navigator.usb.requestDevice({ filters: [{ vendorId: 0x2341 }] })
                .then(selectedDevice => {
                    // ...
            })
        }
    })