iT邦幫忙

2026 iThome 鐵人賽

DAY 22
0
Software Development

SyncETA 開發日記:手把手打造你的智慧出發時間推薦 PWA系列 第 22 篇

【Day 22】加入推播通知(例如:延誤提醒)

  • 分享至 

  • xImage
  •  

今天讓 SyncETA Lite 具備推播通知能力,在資料出現異常延誤時主動提醒使用者。


兩種通知,先從簡單的開始

完整的 Web Push 需要後端伺服器搭配 Push API,設定較複雜;今天我們先實作本機通知(Notification API) ,資料在瀏覽器仍在執行時觸發提醒,適合我們目前的前端專案規模。之後如果要做到「App 沒開也能收到通知」,才需要額外導入 Push 服務。


申請通知權限

// src/main.js
async function requestNotificationPermission() {
  if (!('Notification' in window)) return false;
  const permission = await Notification.requestPermission();
  return permission === 'granted';
}

在資料更新時檢查是否需要提醒

回到 Day 10 的輪詢邏輯,加入延誤判斷:

// src/main.js
const NORMAL_ETA_THRESHOLD = 15; // 假設超過 15 分鐘視為明顯延誤

async function loadArrivals() {
  const raw = await fetchBusArrivals('Taipei', '0100000A00');
  const arrivals = normalizeArrivals(raw);
  renderArrivalList(arrivalContainer, arrivals);

  const nextBus = arrivals[0];
  if (nextBus && nextBus.etaMinutes > NORMAL_ETA_THRESHOLD) {
    notifyDelay(nextBus);
  }
}

function notifyDelay(bus) {
  if (Notification.permission !== 'granted') return;
  new Notification('SyncETA 延誤提醒', {
    body: `${bus.stopName} 目前預估需要 ${bus.etaMinutes} 分鐘,建議調整出發時間`,
    icon: '/icons/icon-192.png',
  });
}

避免通知轟炸

如果每 30 秒輪詢一次都符合延誤條件,使用者會被通知洗版。加入一個簡單的節流機制:

let lastNotifiedAt = 0;
const NOTIFY_COOLDOWN_MS = 10 * 60 * 1000; // 10 分鐘內不重複通知

function notifyDelay(bus) {
  const now = Date.now();
  if (now - lastNotifiedAt < NOTIFY_COOLDOWN_MS) return;
  if (Notification.permission !== 'granted') return;

  lastNotifiedAt = now;
  new Notification('SyncETA 延誤提醒', {
    body: `${bus.stopName} 目前預估需要 ${bus.etaMinutes} 分鐘,建議調整出發時間`,
    icon: '/icons/icon-192.png',
  });
}

這種「重要但不打擾」的通知設計原則,其實跟我研究中提到的「群組延誤通知」功能是同一個精神:只在真正需要決策調整時提醒使用者,而不是每次資料更新都發送。

明天,我們要來處理不同裝置尺寸下的畫面呈現,讓 SyncETA Lite 在手機上也一樣好用。


上一篇
【Day 21】PWA 離線功能:Service Worker 快取策略
下一篇
【Day 23】響應式設計:手機/桌面都好用
系列文
SyncETA 開發日記:手把手打造你的智慧出發時間推薦 PWA 共 23 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言