Skip to content

WebSocket 助手

¥WebSocket Helper

WebSocket Helper 是 Hono 应用中服务器端 WebSockets 的助手。目前 Cloudflare Workers / Pages、Deno 和 Bun 适配器可用。

¥WebSocket Helper is a helper for server-side WebSockets in Hono applications. Currently Cloudflare Workers / Pages, Deno, and Bun adapters are available.

导入

¥Import

ts
import { Hono } from 'hono'
import { upgradeWebSocket } from 'hono/cloudflare-workers'
ts
import { Hono } from 'hono'
import { upgradeWebSocket } from 'hono/deno'
ts
import { Hono } from 'hono'
import { createBunWebSocket } from 'hono/bun'
import type { ServerWebSocket } from 'bun'

const { upgradeWebSocket, websocket } =
  createBunWebSocket<ServerWebSocket>()

// ...

export default {
  fetch: app.fetch,
  websocket,
}

如果你使用 Node.js,则可以使用 @hono/node-ws

¥If you use Node.js, you can use @hono/node-ws.

upgradeWebSocket()

upgradeWebSocket() 返回用于处理 WebSocket 的处理程序。

¥upgradeWebSocket() returns a handler for handling WebSocket.

ts
const app = new Hono()

app.get(
  '/ws',
  upgradeWebSocket((c) => {
    return {
      onMessage(event, ws) {
        console.log(`Message from client: ${event.data}`)
        ws.send('Hello from server!')
      },
      onClose: () => {
        console.log('Connection closed')
      },
    }
  })
)

可用事件:

¥Available events:

  • onOpen - 目前,Cloudflare Workers 不支持它。

    ¥onOpen - Currently, Cloudflare Workers does not support it.

  • onMessage

  • onClose

  • onError

警告

如果你在使用 WebSocket Helper 的路由上使用修改标头的中间件(例如,应用 CORS),则可能会遇到错误,提示你无法修改不可变标头。这是因为 upgradeWebSocket() 也在内部更改标头。

¥If you use middleware that modifies headers (e.g., applying CORS) on a route that uses WebSocket Helper, you may encounter an error saying you can't modify immutable headers. This is because upgradeWebSocket() also changes headers internally.

因此,如果你同时使用 WebSocket Helper 和中间件,请谨慎使用。

¥Therefore, please be cautious if you are using WebSocket Helper and middleware at the same time.

RPC 模式

¥RPC-mode

使用 WebSocket Helper 定义的处理程序支持 RPC 模式。

¥Handlers defined with WebSocket Helper support RPC mode.

ts
// server.ts
const wsApp = app.get(
  '/ws',
  upgradeWebSocket((c) => {
    //...
  })
)

export type WebSocketApp = typeof wsApp

// client.ts
const client = hc<WebSocketApp>('http://localhost:8787')
const socket = client.ws.$ws() // A WebSocket object for a client

示例

¥Examples

查看使用 WebSocket Helper 的示例。

¥See the examples using WebSocket Helper.

服务器和客户端

¥Server and Client

ts
// server.ts
import { Hono } from 'hono'
import { upgradeWebSocket } from 'hono/cloudflare-workers'

const app = new Hono().get(
  '/ws',
  upgradeWebSocket(() => {
    return {
      onMessage: (event) => {
        console.log(event.data)
      },
    }
  })
)

export default app
ts
// client.ts
import { hc } from 'hono/client'
import type app from './server'

const client = hc<typeof app>('http://localhost:8787')
const ws = client.ws.$ws(0)

ws.addEventListener('open', () => {
  setInterval(() => {
    ws.send(new Date().toString())
  }, 1000)
})

带有 JSX 的 Bun

¥Bun with JSX

tsx
import { Hono } from 'hono'
import { createBunWebSocket } from 'hono/bun'

const { upgradeWebSocket, websocket } = createBunWebSocket()

const app = new Hono()

app.get('/', (c) => {
  return c.html(
    <html>
      <head>
        <meta charset='UTF-8' />
      </head>
      <body>
        <div id='now-time'></div>
        <script
          dangerouslySetInnerHTML={{
            __html: `
        const ws = new WebSocket('ws://localhost:3000/ws')
        const $nowTime = document.getElementById('now-time')
        ws.onmessage = (event) => {
          $nowTime.textContent = event.data
        }
        `,
          }}
        ></script>
      </body>
    </html>
  )
})

const ws = app.get(
  '/ws',
  upgradeWebSocket((c) => {
    let intervalId
    return {
      onOpen(_event, ws) {
        intervalId = setInterval(() => {
          ws.send(new Date().toString())
        }, 200)
      },
      onClose() {
        clearInterval(intervalId)
      },
    }
  })
)

export default {
  fetch: app.fetch,
  websocket,
}

Hono v4.7 中文网 - 粤ICP备13048890号