getUserMedia - 如果用户没有选择怎么办?

getUserMedia - what if user makes no choice?

我改编了一个库来通过用户的麦克风录制 MP3 音频。如果用户允许或拒绝麦克风访问请求,我很好,但我注意到 MDN says this:

Note that it is possible for the returned promise to neither resolve nor reject, as the user is not required to make a choice.

但它似乎没有说什么,如果有的话,我可以抓住那个 "no choice made" 动作。如果用户只是退出对话框,或者在没有做出选择的情况下模糊掉它,我可以抓住它并相应地调整我的 UI 吗?

这是我当前的代码:

navigator.mediaDevices.getUserMedia({audio: true}).then(function(stream) {
    build_ui();
    startUserMedia(stream);
}).catch(function(e) { //<-- doesn't fire if no choice made
    cfg.no_device_callback && cfg.no_device_callback(e);
});

您可以对您的承诺实施超时。

例如,您可以按如下方式扩展 Promise 对象和原型:

Promise.wait = function (ms) {
    return new Promise(function (resolve) {
        setTimeout(resolve, ms);
    });
};

Promise.prototype.timeout = function(ms) {
    return Promise.race([
        this, 
        Promise.wait(ms).then(function () {
            throw new Error("time out");
        })
    ])
};

一旦你有了它,你就可以链接 .timeout(10000):

navigator.mediaDevices.getUserMedia({audio: true})
         .timeout(10000).then(function(stream) {
//       ^^^^^^^^^^^^^^^
    build_ui();
    startUserMedia(stream);
}).catch(function(e) { //<-- now also fires if no choice made within 10 secs
    cfg.no_device_callback && cfg.no_device_callback(e);
});

Firefox (57) 不允许 用户关闭权限对话框。此对话框将无限期保持可见,直到您做出选择:

Safari (11)不允许用户关闭对话框。除此之外,它还会锁定整个浏览器(包括其他选项卡),从而迫使用户做出选择:

Chrome (62) 允许 用户通过右上角的 [x] 按钮关闭对话框:

在这种情况下,选择和操作是显而易见的,因此 Chrome 会抛出一个名为 PermissionDismissedError 的非规范错误,但此错误可能会在 Chrome 64 中被删除,它试图朝着符合规范的方向发展错误(参见 this Chromium bug)。

我在 this article 中写了更多 getUserMedia 个错误。