Notification.requestPermission 如果用户启用了更安静的消息传递,承诺将永远不会得到解决

Notification.requestPermission promise is never resolved if user has quieter messaging enabled

我们的网站上有一个滑块按钮,用户可以在其中选择浏览器推送通知。我们最近注意到 chromium 功能“更安静的消息传递”在我们的实施中导致了一些问题。我们总是评估 requestPermission 的返回承诺,以告诉用户他们的操作是否真的有效。但是,如果启用该设置,承诺永远不会得到解决(或拒绝),除非用户点击“允许”。

async function init() {
    var permission = await Notification.requestPermission();
    alert(permission); // This is never called in this case
}
init();

我们想告诉用户他们的操作(启用通知)是否真的有效,或者他们是否需要检查他们的浏览器设置。有没有比单独的超时承诺更好的方法?

这是我目前对解决方法的最佳猜测:

// https://italonascimento.github.io/applying-a-timeout-to-your-promises/
const promiseTimeout = function (ms, promise) {
    // Create a promise that rejects in <ms> milliseconds
    let timeout = new Promise((resolve, reject) => {
        let id = setTimeout(() => {
            clearTimeout(id);
            reject('Timed out in ' + ms + 'ms.')
        }, ms)
    })
    // Returns a race between our timeout and the passed in promise
    return Promise.race([
        promise,
        timeout
    ])
}

async function init() {
    var permissionPromise = Notification.requestPermission();
    try {
        var p = await promiseTimeout(1000/*some magic number*/, permissionPromise);
        alert(p);
    } catch (error) {
        alert(error);
    }
}
init();

发布我的解决方法作为答案,因为目前似乎没有更好的其他解决方案。

// https://italonascimento.github.io/applying-a-timeout-to-your-promises/
const promiseTimeout = function (ms, promise) {
    // Create a promise that rejects in <ms> milliseconds
    let timeout = new Promise((resolve, reject) => {
        let id = setTimeout(() => {
            clearTimeout(id);
            reject('Timed out in ' + ms + 'ms.')
        }, ms)
    })
    // Returns a race between our timeout and the passed in promise
    return Promise.race([
        promise,
        timeout
    ])
}

async function init() {
    var permissionPromise = Notification.requestPermission();
    try {
        var p = await promiseTimeout(1000/*some magic number*/, permissionPromise);
        alert(p);
    } catch (error) {
        alert(error);
    }
}
init();