You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

多设备用户Web Push通知最优处理及对战答题App推送实现技术问询

Hey there! Let's tackle your two Web Push questions—they're both super relevant for real-world web apps, so I’ll share what I’ve learned from building similar systems.

1. Optimal Approach for Web Push with Multi-Device Users

When a user has multiple devices, the key is to balance reach, relevance, and avoiding annoyance. Here’s the best practice breakdown:

  • Link Push Subscriptions to User Identities: First, your backend needs to map each user account to all their active push subscriptions (the PushSubscription objects generated when a user opts in). Every time a user logs into a new device and enables push, send the new subscription to your backend and associate it with their user ID. Don’t forget to clean up stale subscriptions: if you get a 410 Gone response when sending a push, that subscription is invalid (user cleared browser data, unsubscribed, etc.)—remove it from the user’s device list immediately.
  • Target Notifications Strategically: Don’t blast the same notification to every device. Track which devices the user is actively using (via frontend heartbeats or the Page Visibility API, sent to your backend) and only send notifications to idle devices. Alternatively, let users set preferences (e.g., "only send game notifications to my phone") and honor those when triggering pushes.
  • Sync Preferences Across Devices: If a user turns off a notification type on one device, update that preference across all their linked subscriptions in your backend. This ensures consistent behavior no matter which device they’re using.
  • Avoid Duplicate Clutter: If you do need to send notifications to multiple devices, use the tag field in your push options. Notifications with the same tag will replace existing ones on a device, so you won’t end up with 5 identical alerts cluttering their notification center.

2. Web Push for Turn-Based 2-Player Quiz Apps

Let’s start with the optimal solution, then cover fallback options if you hit constraints.

Optimal Solution (Real-Time Push Triggers)

This relies on backend state management paired with Service Workers and the Push API:

  1. Track Game State on the Backend: Maintain a database record for each game that includes the current turn (user A or B) and both users’ active push subscriptions.
  2. Trigger Push on Turn Completion: When user A submits their answer, your frontend calls a backend API to update the game state to "user B’s turn." The backend immediately initiates a push to all valid subscriptions linked to user B.
    • Craft a payload with context: Include game ID and action data so the notification can deep-link directly to the game. Example payload:
      {
        "title": "Your Turn to Answer!",
        "body": "Your opponent just finished their round—don’t keep them waiting!",
        "data": {"gameId": "quiz-game-123", "route": "/game/123"}
      }
      
  3. Service Worker Handling: Use your service worker to display notifications and handle clicks:
    // Listen for incoming push events
    self.addEventListener('push', (event) => {
      const payload = event.data?.json() || {};
      const notificationOptions = {
        body: payload.body,
        data: payload.data,
        icon: '/quiz-app-icon.png',
        badge: '/notification-badge.png'
      };
      event.waitUntil(self.registration.showNotification(payload.title, notificationOptions));
    });
    
    // Handle notification clicks to deep-link to the game
    self.addEventListener('notificationclick', (event) => {
      event.notification.close();
      // Open the game page, or focus an existing tab if it's already open
      event.waitUntil(
        clients.matchAll({ type: 'window', includeUncontrolled: true })
          .then((clientList) => {
            for (const client of clientList) {
              if (client.url.includes(event.notification.data.gameId) && 'focus' in client) {
                return client.focus();
              }
            }
            if (clients.openWindow) {
              return clients.openWindow(event.notification.data.route);
            }
          })
      );
    });
    
  4. Skip Push for Active Users: Before sending a push, check if user B has an active session (via recent heartbeats). If they’re currently playing on any device, skip the push to avoid annoying them mid-game.
  5. Refresh Expired Subscriptions: Have your frontend listen for the pushsubscriptionchange event—this fires when a subscription becomes invalid. When it does, re-subscribe the user and send the new subscription to your backend to update their device list.

Feasible Fallback Solutions

If real-time backend triggers aren’t feasible (e.g., limited backend resources, complex state management), try these:

  • Background Polling via Service Worker: Use a service worker to periodically call your backend API (every 3–5 minutes, for example) to check if it’s the user’s turn. If it is, display a local notification directly from the service worker. This avoids the need for backend-initiated pushes but introduces some delay.
  • Scheduled Backend Scans: Instead of triggering pushes in real-time, have your backend run a periodic job (every 1 minute) that scans all games waiting for a user’s turn. For each pending game, send a push to the waiting user. This reduces backend complexity compared to real-time triggers, with minimal delay.
  • WebRTC Peer-to-Peer (Limited Use Case): If both users are online, use WebRTC to establish a direct connection. When one user finishes their turn, send a message directly to the other user’s browser to trigger a local notification. This works great for active sessions but fails if either user is offline, so it’s best used as a supplement to push, not a replacement.

内容的提问来源于stack exchange,提问作者Sebastian

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 07:48:48