【问题标题】:Browser push notifications not responding after some time浏览器推送通知在一段时间后没有响应
【发布时间】:2018-04-18 11:59:12
【问题描述】:

我遇到了一个奇怪的问题,似乎找不到任何解决方案。我为用户订阅我的网络推送服务,当他们收到通知时,我会跟踪通知显示的时间,如果它被点击或关闭。但是,当我发送带有需要交互标志或持久标志的通知并将其打开大约 1 分钟时,它会被禁用。

我所说的禁用是什么意思:

  • 不能点击按钮
  • 无法自行点击通知
  • 只能点击X关闭它

然后当用户关闭通知或系统关闭它时,我的服务人员不会注册关闭事件。

我在 Firefox 上遇到的问题之一是,当用户点击通知时,它只关注 Firefox 中的空选项卡。

这是我的服务工作者代码:

self.addEventListener('push', function(event) {

console.log('[Service Worker] Push Received.');

data = event.data.json();
const title = data.title;
const options = data.options;

event.waitUntil(
  self.registration.showNotification(title, options)
  .then((notificationEvent)=>{

    let payload = {
      campaign_id: data.campaign_id,
      subscriber_id:data.subscriber_id,
      action:'display'
    }

   sendData(api_url+'touch',payload,'display');

 })
);
});

self.addEventListener('notificationclick',function(event){

  if(data.url){
  console.log('Notification clicked !');

  const clickedNotification = event.notification;
  let   promiseChain = null;

  clickedNotification.close();

  let payload = {
    campaign_id: data.campaign_id,
    subscriber_id:data.subscriber_id,
    action:'click'
  }

  if(event.action === 'button1Link')
  {
    promiseChain = clients.openWindow(data.button1Link);
  }else if(event.action === 'button2Link')
  {
    promiseChain = clients.openWindow(data.button2Link);
  }else if(event.action === 'button3Link')
  {
    promiseChain = clients.openWindow(data.button3Link);
  }else if(event.action === 'closeButton')
  {
    payload.action = 'close';
  }else
  {
    promiseChain = clients.openWindow(data.url);
  }

  sendData(api_url+'touch',payload).then(()=>console.log('Stat 
  sent!'));

  event.waitUntil(promiseChain);
}

})

self.addEventListener('notificationclose',function(event){

  console.log('Notification closed !');

  let payload = {
      campaign_id: data.campaign_id,
      subscriber_id:data.subscriber_id,
      action:'close'
    }

  event.waitUntil(sendData(api_url+'touch',payload,'close'));

})



function sendData(url,payload)
{

  let data = new FormData();

  Object.keys(payload).map((field)=>{
    data.append(field,payload[field]);
  });

  return fetch(api_url+'touch', {
      method: 'POST', 
      body: data,
      mode:'cors'
     });
}

我真的可以使用一些建议和帮助,因为我在整个网络上查找了发生这种情况的原因,但似乎找不到任何有用的东西。

我的有效载荷结构如下所示:

   array(7) {
  ["title"]=>
  string(25) "Noise reducing headphones"
  ["url"]=>
  string(76) "https://www.bestbuy.com/site/audio/headphones/abcat0204000.c?id=abcat0204000"
  ["campaign_id"]=>
  string(2) "49"
  ["button1Link"]=>
  string(120) "https://cdn.iconscout.com/public/images/icon/premium/png-512/headphones-phones-music-player-3b0242ebbd8df45e-512x512.png"
  ["button2Link"]=>
  string(120) "https://cdn.iconscout.com/public/images/icon/premium/png-512/headphones-phones-music-player-3b0242ebbd8df45e-512x512.png"
  ["button3Link"]=>
  string(120) "https://cdn.iconscout.com/public/images/icon/premium/png-512/headphones-phones-music-player-3b0242ebbd8df45e-512x512.png"
  ["options"]=>
  array(7) {
    ["actions"]=>
    array(3) {
      [0]=>
      array(2) {
        ["action"]=>
        string(11) "button1Link"
        ["title"]=>
        string(5) "Order"
      }
      [1]=>
      array(2) {
        ["action"]=>
        string(11) "button2Link"
        ["title"]=>
        string(6) "Cancel"
      }
      [2]=>
      array(2) {
        ["action"]=>
        string(11) "button3Link"
        ["title"]=>
        string(17) "Order on facebook"
      }
    }
    ["body"]=>
    string(40) "Listen to your music without disturbance"
    ["image"]=>
    string(56) "campaignimg1.jpg"
    ["icon"]=>
    string(53) "image2.png"
    ["vibrate"]=>
    array(1) {
      [0]=>
      string(0) ""
    }
    ["silent"]=>
    bool(false)
    ["requireInteraction"]=>
    bool(false)
  }
}

【问题讨论】:

    标签: google-chrome firefox push-notification notifications service-worker


    【解决方案1】:

    所以我弄清楚我的服务人员出了什么问题......

    首先重建我的承诺:

    notificationclick 监听器现在看起来像这样:

    self.addEventListener('notificationclick',function(event){
    const clickedNotification = event.notification;
    
      if(clickedNotification.data.url){
    
      let   openWindowEvent = null;
    
      clickedNotification.close();
    
      let payload = {
        campaign_id: clickedNotification.data.campaign_id,
        subscriber_id:clickedNotification.data.subscriber_id,
        action:'click'
      }
    
      if(event.action === 'button1Link')
      {
        openWindowEvent = clients.openWindow(clickedNotification.data.button1Link);
      }else if(event.action === 'button2Link')
      {
        openWindowEvent = clients.openWindow(clickedNotification.data.button2Link);
      }else if(event.action === 'button3Link')
      {
        openWindowEvent = clients.openWindow(clickedNotification.data.button3Link);
      }else if(event.action === 'closeButton')
      {
        payload.action = 'close';
      }else
      {
        openWindowEvent = clients.openWindow(clickedNotification.data.url);
      }
    
      payload = prepareData(payload);
    
      const sendStat = fetch(api_url+'touch', {
          method: 'POST', 
          body: payload,
          mode:'cors'
         });
    
      const promiseChain = Promise.all([
          openWindowEvent,
          sendStat
        ]);
    
      event.waitUntil(promiseChain);
    }
    })
    

    Channing Promise 帮助 Service Worker 长时间保持活力,直到所有任务都完成。

    我还重建了 onclose 事件监听器,所以现在看起来像这样:

      self.addEventListener('notificationclose',function(event){
    
          const closedNotification = event.notification;
    
          console.log('Notification closed !');
    
          let payload = {
              campaign_id: closedNotification.data.campaign_id,
              subscriber_id: closedNotification.data.subscriber_id,
              action:'close'
            }
    
          payload = prepareData(payload);
    
          const promiseChain = fetch(api_url+'touch', {
              method: 'POST', 
              body: payload,
              mode:'cors'
             });
    
          event.waitUntil(promiseChain);
    
      })
    

    一段时间后禁用我的通知的主要问题是访问数据。当'push'事件触发时,我试图保存从服务器发送的数据时犯了一个错误......这没关系,直到浏览器决定杀死服务人员。然后你会丢失所有存储在变量中的数据。

    解决方案:

    使用传递给所有事件侦听器的变量“事件”访问从服务器发送的数据:

    self::addEventListener('notificationclick',function(event){});
    

    您可以从那里访问随通知发送的所有数据并根据需要使用它。这解决了不使用发送的 url 打开新标签并注册关闭事件的问题。

    【讨论】:

    • 谢谢。您的解决方案使我专注于真正的问题,即“您不应该在 ServiceWorker 上持久化数据”,但您可以在 Notification 上持久化。当我在我的服务人员上调用self.registration.showNotification(title, options) 时,我在options.data 中传递我的参数。它完美无瑕,谢谢。
    • @LimaChaves,你的想法对我很有效。在self.addEventListener('push', function(event){}); 中,我将 url 添加到 options.data。然后在self.addEventListener('notificationclick', function(event){}); 我从event.notification.data 中检索到它。除了通知选项中的数据对象之外,似乎不应将数据保留在其他任何地方。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多