Notification.requestPermission 在 Mac 版本的 Safari 中引发错误
Posted
技术标签:
【中文标题】Notification.requestPermission 在 Mac 版本的 Safari 中引发错误【英文标题】:Notification.requestPermission throws an error in Mac versions of Safari 【发布时间】:2016-11-02 00:39:24 【问题描述】:我正在尝试在页面加载时使用 jQuery 在本地显示通知。通知在 Firefox、Firefox Developer 和 Chrome 中正确显示。尽管通知首选项设置允许,但通知未显示在 Safari 中。
MDN 站点 https://developer.mozilla.org/en/docs/Web/API/notification 上的类似代码正在运行。
片段如下。
// Display a sample notification
if (window.Notification)
return $(".au-notifications-page").show(function()
var notification;
notification = new Notification(
'Success Text',
//tag: $("[name=tag]").val(),
body: 'Success Message',
iconUrl: 'img/avatar-male.png',
icon: 'img/avatar-male.png'
);
return notification.onclick = function()
notification.close();
window.open().close();
return window.focus();
;
);
;
完整代码如下。
$(document).ready(function ()
// Request permission on site load
Notification.requestPermission().then(function(result)
if (result === 'denied')
//alert('denied');
$(".au-notif-disabled-header").removeClass('hide');
$(".au-notif-disabled-header .btn").addClass('hide');
return;
if (result === 'default')
//alert('ignored');
$(".au-notif-disabled-header").removeClass('hide');
return;
//alert('granted');
$(".au-notif-disabled-header").addClass('hide');
);
// Request permission with button
$('.au-notif-disabled-header .btn').click(function ()
Notification.requestPermission().then(function(result)
if (result === 'denied')
$(".au-notif-disabled-header").removeClass('hide');
$(".au-notif-disabled-header .btn").addClass('hide');
return;
if (result === 'default')
$(".au-notif-disabled-header").removeClass('hide');
return;
$(".au-notif-disabled-header").addClass('hide');
);
);
$( ".au-notification-icon" ).hover(
function()
$(".au-notifications-menu .au-notif-msg-realtime").slideDown();
$('.au-notification-icon .badge').html("2");
, function()
$(".au-notifications-menu .au-notif-msg-realtime").slideUp();
$('.au-notification-icon .badge').html("1");
);
//To show notification received while on notifications page
$(".au-notif-msg-realtime").hide();
//$(".au-notifications-page .au-notif-msg-realtime").slideDown();
$(".au-notifications-page .au-notif-msg-realtime").slideDown(
complete: function()
$('.au-notification-icon .badge').html("2");
$('head title').html("(2) Notifications");
);
// Display a sample notification
if (window.Notification)
return $(".au-notifications-page").show(function()
var notification;
notification = new Notification(
'Success Heading',
body: 'Success Text',
iconUrl: 'img/avatar-male.png',
icon: 'img/avatar-male.png'
);
return notification.onclick = function()
notification.close();
window.open().close();
return window.focus();
;
);
;
);
编辑 1:Safari 抛出此异常
undefined 不是对象(评估 'Notification.requestPermission().then')
【问题讨论】:
【参考方案1】:您必须为 Safari 使用回调函数,因为它不会返回 Promise。
根据MDN:
这使用了该方法的 promise-version,正如最近支持的那样 实现(例如 Firefox 47。)如果你想支持 旧版本,您可能必须使用旧回调版本, 看起来像这样:
这是他们提供的示例代码:
Notification.requestPermission(function (permission)
// If the user accepts, let's create a notification
if (permission === "granted")
var notification = new Notification("Hi there!");
);
为了支持 Safari 通知,我最终得到了这样的结果:
try
Notification.requestPermission()
.then(() => doSomething())
catch (error)
// Safari doesn't return a promise for requestPermissions and it
// throws a TypeError. It takes a callback as the first argument
// instead.
if (error instanceof TypeError)
Notification.requestPermission(() =>
doSomething();
);
else
throw error;
【讨论】:
由于某些浏览器(即 ios 11.4 上的 Safari)不支持Notification
,因此在执行 try/catch 块之前检查 typeof Notification !== 'undefined'
可能是一个好习惯。【参考方案2】:
更好的解决方案是将结果包装在Promise
中,然后然后(没有双关语)运行您的代码。此代码适用于所有浏览器(包括 Safari),并且没有复杂的 if
块(概念在 this question 中有详细讨论)
Promise.resolve(Notification.requestPermission()).then(function(permission)
// Do something
);
这是因为Promise.resolve
对Promise
没有任何作用,但会将Safari 的requestPermission()
转换为Promise
。
请注意,iOS Safari 仍然不支持 Notification API,因此您需要 check if it is available first
【讨论】:
在 safari 上,权限在 Safari 上是未定义的,对吧?permission
只是我选择的参数名称。 promise 会将通知权限对象传递给回调函数
这不起作用,因为Notification.requestPermission()
在Safari上立即返回undefined
,then
函数会立即被调用,无需等待权限请求对话框被解析,并且不管用户选择什么。【参考方案3】:
要返回一个在用户授予或拒绝显示通知的权限之前不会解析的承诺:
if (!permissionPromise && Notification.permission === 'granted' )
permissionPromise = Promise.resolve(Notification.permission);
if (!permissionPromise)
permissionPromise = new Promise(function (resolve, reject)
// Safari uses callback, everything else uses a promise
var maybePromise = $window.Notification.requestPermission(resolve, reject);
if (maybePromise && maybePromise.then)
resolve(maybePromise);
);
return permissionPromise;
【讨论】:
以上是关于Notification.requestPermission 在 Mac 版本的 Safari 中引发错误的主要内容,如果未能解决你的问题,请参考以下文章