实时快速入门
学习如何构建multiplayer.dev,这是一个合作应用,它展示了使用实时的广播、Presence和Postgres CDC。
安装supabase-js 客户端 
  
  
  
  
  
  
  
  
  
  npm install @supabase/supabase-js
  
  光标位置
广播允许一个客户端发送消息,多个客户端接收消息。广播的消息是短暂的。它们不会被持久化到数据库中,而是直接通过实时服务器转发。这对于发送像光标位置这样的信息是很理想的,因为最小的延迟是很重要的,但持久化则不是。
在multiplayer.dev中,客户端的光标位置被发送到房间里的其他客户端。然而,在这个例子中,光标位置将是随机生成的。
你需要从你的项目的API设置中获得公共的anon访问令牌。然后你就可以设置Supabase客户端,并开始发送一个客户端的光标位置到通道room1中的其他客户端。
  const { createClient } = require('@supabase/supabase-js')
const supabase = createClient('https://your-project-ref.supabase.co', 'anon-key', {
  realtime: {
    params: {
      eventsPerSecond: 10,
    },
  },
})
// Channel name can be any string.
// Create channels with the same name for both the broadcasting and receiving clients.
const channel = supabase.channel('room1')
// Subscribe registers your client with the server
channel.subscribe((status) => {
  if (status === 'SUBSCRIBED') {
    // now you can start broadcasting cursor positions
    setInterval(() => {
      channel.send({
        type: 'broadcast',
        event: 'cursor-pos',
        payload: { x: Math.random(), y: Math.random() },
      })
      console.log(status)
    }, 100)
  }
})
  
  JavaScript客户端有一个默认的速率限制,即每100毫秒一个实时事件,由eventsPerSecond配置。
另一个客户端可以订阅频道room1并接收游标位置。
  // Supabase client setup
// Listen to broadcast messages.
supabase
  .channel('room1')
  .on('broadcast', { event: 'cursor-pos' }, (payload) => console.log(payload))
  .subscribe((status) => {
    if (status === 'SUBSCRIBED') {
      // your callback function will now be called with the messages broadcast by the other client
    }
  })
  
  type 必须是 broadcast,event 必须与订阅该频道的客户相匹配。
往返延时
你也可以配置通道,使服务器必须返回一个确认函,表明它收到了 “广播 “信息。如果你想测量往返的延迟,这很有用。
  // Supabase client setup
const channel = supabase.channel('calc-latency', {
  config: {
    broadcast: { ack: true },
  },
})
channel.subscribe(async (status) => {
  if (status === 'SUBSCRIBED') {
    const begin = performance.now()
    await channel.send({
      type: 'broadcast',
      event: 'latency',
      payload: {},
    })
    const end = performance.now()
    console.log(`Latency is ${end - begin} milliseconds`)
  }
})
  
  跟踪和显示哪些用户在线
Presence存储和同步各客户端的共享状态。每当共享状态发生变化时,就会触发sync事件。join事件在新客户加入频道时被触发,leave事件在客户离开时被触发。
每个客户端可以使用通道的track方法来存储共享状态中的对象。每个客户端只能跟踪一个对象,如果track被同一个客户端再次调用,那么新的对象就会覆盖共享状态中先前跟踪的对象。你可以使用一个客户端来跟踪和显示在线的用户。
  // Supabase client setup
const channel = supabase.channel('online-users', {
  config: {
    presence: {
      key: 'user1',
    },
  },
})
channel.on('presence', { event: 'sync' }, () => {
  console.log('Online users: ', channel.presenceState())
})
channel.on('presence', { event: 'join' }, ({ newPresences }) => {
  console.log('New users have joined: ', newPresences)
})
channel.on('presence', { event: 'leave' }, ({ leftPresences }) => {
  console.log('Users have left: ', newPresences)
})
channel.subscribe(async (status) => {
  if (status === 'SUBSCRIBED') {
    const status = await channel.track({ online_at: new Date().toISOString() })
    console.log(status)
  }
})
  
  然后,您可以使用其他客户端将其他用户添加到频道的存在状态:
  // Supabase client setup
const channel = supabase.channel('online-users', {
  config: {
    presence: {
      key: 'user2',
    },
  },
})
// Presence event handlers setup
channel.subscribe(async (status) => {
  if (status === 'SUBSCRIBED') {
    const status = await channel.track({ online_at: new Date().toISOString() })
    console.log(status)
  }
})
  
  如果一个频道在没有存在密钥的情况下被设置,服务器会生成一个随机的UUID。type必须是presence,event必须是sync,join,或leave。
插入和接收持久的信息
Postgres Change Data Capture (CDC)使你的客户能够插入、更新或删除数据库记录,并将这些变化发送给客户。创建一个messages表来跟踪用户在特定房间创建的消息。
  create table messages (
  id serial primary key,
  message text,
  user_id text,
  room_id text,
  created_at timestamptz default now()
)
alter table messages enable row level security;
create policy "anon_ins_policy"
ON messages
for insert
to anon
with check (true);
create policy "anon_sel_policy"
ON messages
for select
to anon
using (true);
  
  如果它还不存在,创建一个supabase_realtime发布,并将messages表添加到该出发布中。
  begin;
  -- remove the supabase_realtime publication
  drop publication if exists supabase_realtime;
  -- re-create the supabase_realtime publication with no tables and only for insert
  create publication supabase_realtime with (publish = 'insert');
commit;
-- add a table to the publication
alter publication supabase_realtime add table messages;
  
  然后你可以让客户端监听特定房间的messages表的变化,并发送和接收持久化的信息。
  // Supabase client setup
const channel = supabase.channel('db-messages')
const roomId = 'room1'
const userId = 'user1'
channel.on(
  'postgres_changes',
  {
    event: 'INSERT',
    schema: 'public',
    table: 'messages',
    filter: `room_id=eq.${roomId}`,
  },
  (payload) => console.log(payload)
)
channel.subscribe(async (status) => {
  if (status === 'SUBSCRIBED') {
    const res = await supabase.from('messages').insert({
      room_id: roomId,
      user_id: userId,
      message: 'Welcome to Realtime!',
    })
    console.log(res)
  }
})