我正在通过Chrome版本42.0.2311.152M进行测试,我想实现以在此示例中像NotificationClick上打开一个窗口:(来源:https://ddeveloper..mozilla。org/en-us/docs/web/api/windowclient)
self.addEventListener('notificationclick', function(event) {
console.log('On notification click: ', event.notification.tag);
event.notification.close();
// This looks to see if the current is already open and
// focuses if it is
event.waitUntil(clients.matchAll({
type: "window"
}).then(function(clientList) {
for (var i = 0; i < clientList.length; i++) {
var client = clientList[i];
if (client.url == '/' && 'focus' in client)
return client.focus();
}
if (clients.openWindow)
return clients.openWindow('/');
}));
});
我的档案表现就像:
https://myurl.no-ip.org/app/index.html
https://myurl.no-ip.org/app/manifest.json
https://myurl.no-ip.org/app/service-worker.js
我有一个我总是得到
的问题invalidaccesserror
呼叫client.openwindow('/')或clienter.openwindow('https://myurl.no-ip.org/app/app/index.html'):
{code: 15,
message: "Not allowed to open a window.",
name: "InvalidAccessError"}
" return client.focus()"行永远不会达到线,因为client.url永远不只是'/'。看
clients.matchAll({type: "window"})
.then(function (clientList) {
console.log(clientList[0])});
我看到我当前的窗口:
{focused: false,
frameType: "top-level",
url: "https://myurl.no-ip.org/app/index.html",
visibilityState: "hidden" }
属性"聚焦"one_answers"可访问性态"是正确的。
通过手动焦点呼叫
clients.matchAll({type: "window"})
.then(function (clientList) {
clientList[0].focus()});
我收到错误:
{code: 15,
message: "Not allowed to focus a window.",
name: "InvalidAccessError"}
我认为问题是URL不仅是'/'。您对此有什么想法吗?
非常感谢!
最好的问候
Andi
您的代码对我来说正常工作,因此我将解释使用openWindow
/focus
的要求,以及如何避免"不允许[打开| focus]窗口"错误)"消息。
clients.openWindow()
和 windowClient.focus()
仅在单击通知(至少在Chrome 47中)后才允许使用,并且最多可以在单击处理程序的时间内调用这些方法中的一个。此行为是在https://github.com/slightlyoff/serviceworker/issues/602中指定的。
如果您的openWindow
/focus
呼叫被错误消息拒绝
"不允许打开窗口。"对于
openWindow
"不允许聚焦窗户。"对于focus
那么您不满足openWindow
/focus
的要求。例如(所有点也适用于focus
,而不仅仅是openWindow
)。
-
openWindow
在未单击通知时被调用。 -
openWindow
在notificationclick
处理程序返回后被调用,而您没有带有承诺的event.waitUntil
。 -
openWindow
在解决了event.waitUntil
的承诺后被调用。 - 诺言没有得到解决,但花了"太长"(Chrome 10秒),因此临时致电
openWindow
过期。
确实有必要最多一次调用openWindow
/focus
,并且在notificationclick
处理程序完成之前。
正如我之前所说的,问题中的代码可行,所以我将展示另一个注释的示例。
// serviceworker.js
self.addEventListener('notificationclick', function(event) {
// Close notification.
event.notification.close();
// Example: Open window after 3 seconds.
// (doing so is a terrible user experience by the way, because
// the user is left wondering what happens for 3 seconds.)
var promise = new Promise(function(resolve) {
setTimeout(resolve, 3000);
}).then(function() {
// return the promise returned by openWindow, just in case.
// Opening any origin only works in Chrome 43+.
return clients.openWindow('https://example.com');
});
// Now wait for the promise to keep the permission alive.
event.waitUntil(promise);
});
index.html
<button id="show-notification-btn">Show notification</button>
<script>
navigator.serviceWorker.register('serviceworker.js');
document.getElementById('show-notification-btn').onclick = function() {
Notification.requestPermission(function(result) {
// result = 'allowed' / 'denied' / 'default'
if (result !== 'denied') {
navigator.serviceWorker.ready.then(function(registration) {
// Show notification. If the user clicks on this
// notification, then "notificationclick" is fired.
registration.showNotification('Test');
});
}
});
}
</script>
ps。服务工作者仍在开发中,因此值得一提的是,我已经验证了以上言论在Chrome 49中是正确的,并且该示例在Chrome 43 中起作用(并且打开/
而不是https://example.com
也可以在Chrome 42中起作用)。/p>
这对我有用
您应该定义运营完成后会发射的承诺。
示例Bellow展示了如何返回链接的诺言
首先承诺返回Windows列表。如果不是空的,我们将集中精力并返回Promise.resolve() - 立即解决。
如果找不到窗户,我们要返回下一个锁定的诺言 - 首先在"打开新窗口"中尝试将其集中。
addEventListener('notificationclick', (event) => {
console.log('---- notification clicked ----')
console.log(event)
//using notification data to constract specific path
const data = event.notification.data
console.log(data)
let url = 'https://exmaple.com'
if(data){
url += data['business'] ?
`/business/messages/${data['respondent']}` :
`/store/${data['respondent']}/questions`
}
console.log('new window url: ' + url)
event.notification.close()
//event should wait until we done
event.waitUntil(
//do we have some windows of our app?
self.clients.matchAll({includeUncontrolled: true, type: 'window'})
.then(list=>{
console.log('total clients: '+list.length)
if(list.length === 0){
//no windows of our app. We will open new one
console.log('no clients found')
return self.clients.openWindow(url)
.then((windowClient) => {
//we should focus new window and return Promise to terminate our event
return windowClient ? windowClient.focus() : Promise.resolve()
})
}
const client = list[0]
console.log(client)
//we have a window of our app. Let's focus it and return Promise
client.focus()
console.log('--window focused---')
return Promise.resolve()
}))
})