iT邦幫忙

2025 iThome 鐵人賽

DAY 16
0
Software Development

我獨自開發 - 用 Supabase 打造全端應用系列 第 16

第十六關 - 心靈感應與雙向感知:Supabase Realtime

  • 分享至 

  • xImage
  •  

封面

身為前端開發者,打造一個即時聊天室、一個能即時更新數據的儀表板,這些「即時互動」的應用,往往能大幅提升使用者體驗,要實現這些功能,傳統上需要處理複雜的後端設定、WebSocket 連線管理、資料同步等繁瑣細節,今天介紹的 Supabase Realtime,就是為了解決這些痛點而生。

Supabase Realtime 是什麼?

Supabase Realtime 是一個基於 PostgreSQL 的即時訂閱服務,透過 WebSocket 實現資料庫變更、廣播訊息和用戶狀態同步。它提供了三個核心功能:監聽資料庫變更(Postgres Changes)、即時廣播訊息(Broadcast)、以及用戶在線狀態同步(Presence)。

簡單來說

  1. 資料庫變更通知:就像訂閱了一份報紙,只要資料庫裡有任何新的文章、修改或刪除,它都會立刻送到你手上,讓你隨時掌握最新動態。

  2. 即時廣播:就像一個廣播電台,可以對著麥克風說話,所有收聽同一個頻道的人都能立刻聽到你的聲音。

  3. 在線狀態追蹤:就像進入一個會議室,可以知道誰在裡面、誰離開了,甚至他們現在在做什麼(例如「正在打字」)。

心靈感應與雙向感知:在腦中直接對任何一位、一部分或全體暗影士兵下達命令。這種溝通是即時的,不受距離限制。不僅能下令,還能感知到士兵們的位置、狀態,甚至可以「共享」他們的視野,看到他們所見的景象。

核心概念

要充分運用 Supabase Realtime,需要理解四個核心概念:

Channels (頻道)

Realtime 的基本單位,用於組織和隔離不同的即時通訊流。每個頻道都有一個獨特的名稱,客戶端可以訂閱一個或多個頻道來接收相關訊息。

想像成不同的「聊天室」或「主題房間」,只有加入特定房間的人才能收到裡面的訊息。例如,你可以建立一個「產品討論」頻道讓產品團隊溝通,或是建立一個「遊戲大廳」頻道讓玩家互動。每個頻道都是獨立的,不會互相干擾。

Broadcast (廣播)

允許在頻道內向所有訂閱者發送非持久性、低延遲的訊息。這些訊息不會被儲存到資料庫中,純粹用於即時傳遞短暫的狀態資訊。

就像對著麥克風喊話,所有在同一個房間裡的人都能立刻聽到,但訊息不會被記錄下來。適合傳遞「一閃而過」的即時資訊,例如:

  • 即時游標位置:在 Google Docs 這樣的協同編輯工具中,顯示其他用戶的游標在哪裡
  • 打字狀態:在聊天室中顯示「小明正在打字...」
  • 遊戲狀態同步:多人遊戲中玩家的移動、攻擊等即時動作

Presence (在線狀態)

用於追蹤和同步頻道內用戶的在線狀態及自定義狀態資訊。當用戶加入或離開頻道時,其他訂閱者會收到通知,並且可以獲取當前所有在線用戶的完整狀態列表。

就像進入一個會議室,可以知道誰在裡面、誰離開了,甚至現在在做什麼。例如,在一個線上協作工具中,可以看到哪些同事在線上,是否正在忙碌,或者正在編輯哪個部分。當有人加入或離開時,也會立刻收到通知。

Postgres Changes (資料庫變更)

允許客戶端訂閱 PostgreSQL 資料庫中特定表格的 INSERT, UPDATE, DELETE 事件,並即時接收這些變更。這是基於 PostgreSQL 的邏輯複製功能實現的。

就像訂閱了一份報紙,只要資料庫裡有任何新的文章、修改或刪除,都會立刻收到通知。這對於需要即時更新數據的應用非常有用,例如:

  • 即時儀表板:當銷售數據更新時,圖表立刻刷新
  • 通知系統:有新訂單時,管理員立即收到提醒
  • 聊天應用:新訊息寫入資料庫時,聊天室即時顯示

如何使用 Supabase Realtime

在使用 Supabase Realtime 之前,你需要先初始化 Supabase 客戶端。

import { createClient } from '@supabase/supabase-js'

const supabaseUrl = 'YOUR_SUPABASE_URL'
const supabaseAnonKey = 'YOUR_SUPABASE_ANON_KEY'

const supabase = createClient(supabaseUrl, supabaseAnonKey)

Broadcast

如何在一個頻道中發送和接收廣播訊息。

// 1. 訂閱一個頻道
const myChannel = supabase.channel('my-broadcast-channel')

// 2. 監聽廣播訊息
myChannel.on('broadcast', { event: 'chat-message' }, (payload) => {
  console.log('收到廣播訊息:', payload.payload.message)
}).subscribe()

// 3. 發送廣播訊息 (例如,點擊按鈕時發送)
async function sendMessage() {
  const { error } = await myChannel.send({
    type: 'broadcast',
    event: 'chat-message',
    payload: { message: 'Hello, everyone!' },
  })
  if (error) console.error('發送廣播失敗:', error)
}

// 呼叫 sendMessage() 來發送訊息
// sendMessage()

Presence

如何追蹤和顯示在線用戶的狀態。

// 1. 訂閱一個頻道並啟用 Presence
const presenceChannel = supabase.channel('online-users', {
  config: { presence: { key: 'user_id_123' } } // 為當前用戶設定一個唯一的 key
})

// 2. 監聽 Presence 事件
presenceChannel.on('presence', { event: 'sync' }, () => {
  const presenceState = presenceChannel.presenceState()
  console.log('當前在線用戶狀態:', presenceState)
}).on('presence', { event: 'join' }, ({ newPresences }) => {
  console.log('新用戶加入:', newPresences)
}).on('presence', { event: 'leave' }, ({ leftPresences }) => {
  console.log('用戶離開:', leftPresences)
}).subscribe(async (status) => {
  if (status === 'SUBSCRIBED') {
    // 3. 追蹤當前用戶的狀態
    const { error } = await presenceChannel.track({
      user_name: 'William',
      online_at: new Date().toISOString(),
      status: 'online'
    })
    if (error) console.error('追蹤狀態失敗:', error)
  }
})

// 當用戶離開頁面時,自動移除其狀態
window.addEventListener('beforeunload', () => {
  presenceChannel.untrack()
})

Postgres Changes

要使用 Postgres Changes,需要在 Supabase 後台為你想要監聽的表格啟用 Realtime。

  1. 在 Supabase 後台啟用 Realtime for Tables:

    • 登入你的 Supabase 專案。
    • 導航到「Database」 -> 「Publications」。
    • 選擇你想要啟用 Realtime 的表格,並確保「Enable Realtime」選項已開啟。
  2. 訂閱資料庫變更:

// 1. 訂閱 'public' schema 下 'your_table_name' 表格的所有變更
const tableChannel = supabase.channel('any_table_channel_name')
  .on(
    'postgres_changes',
    { event: '*', schema: 'public', table: 'your_table_name' },
    (payload) => {
      console.log('資料庫變更:', payload)
      // payload.eventType: 'INSERT', 'UPDATE', 'DELETE'
      // payload.new: 新增或更新後的數據
      // payload.old: 刪除或更新前的數據 (僅在 UPDATE/DELETE 時有)
    }
  )
  .subscribe()

// 只監聽特定事件,例如只監聽新增 (INSERT)
supabase.channel('new-rows')
  .on(
    'postgres_changes',
    { event: 'INSERT', schema: 'public', table: 'your_table_name' },
    (payload) => {
      console.log('新增了一行數據:', payload.new)
    }
  )
  .subscribe()

// 或者監聽特定條件的更新
supabase.channel('specific-update')
  .on(
    'postgres_changes',
    { event: 'UPDATE', schema: 'public', table: 'your_table_name', filter: 'id=eq.123' },
    (payload) => {
      console.log('ID 為 123 的數據被更新了:', payload.new)
    }
  )
  .subscribe()

Supabase Dashboard 查看監聽結果

除了在程式碼中處理監聽結果外,也可以直接在 Supabase Dashboard 的 Realtime Inspector 中即時查看和測試頻道訊息:

步驟 1:進入 Realtime Inspector

  1. 登入你的 Supabase 專案
  2. 在左側選單中點選「Realtime」
  3. 選擇「Inspector」工具

步驟 2:加入頻道並開始監聽

  1. 點擊「Join a channel」按鈕
  2. 輸入頻道名稱,例如:my-broadcast-channel
  3. 點擊「Start listening」開始監聽該頻道的所有訊息

步驟 3:查看即時訊息

  • 左側面板會顯示所有接收到的即時訊息列表
  • 點擊任一訊息可在右側面板查看詳細內容
  • 訊息會包含:
    • 事件類型:broadcast、presence 或 postgres_changes
    • 時間戳記:訊息接收的確切時間
    • Payload:完整的訊息內容和資料結構
    • 頻道資訊:訊息來源的頻道名稱

步驟 4:使用篩選功能

  • 點擊「Filter messages」可以篩選特定類型的訊息
  • 可以根據事件類型、頻道名稱等條件進行篩選

實用技巧:

  • 在開發階段,可以同時開啟 Inspector 和你的應用程式,即時對照訊息傳遞情況
  • Inspector 中顯示的 payload 結構與程式碼中接收到的完全相同
  • 適合用來除錯和驗證 Realtime 功能是否正常運作

小結

無論想打造即時聊天應用、協同編輯工具、多人遊戲,還是動態儀表板,Supabase Realtime 都能提供扎實的基礎。

有任何想討論歡迎留言,或需要指正的地方請鞭大力一點,歡迎訂閱、按讚加分享,分享給想要提升開發效率的朋友


上一篇
第十五關 - 影子軍團:Supabase Edge Functions
系列文
我獨自開發 - 用 Supabase 打造全端應用16
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言