[{"data":1,"prerenderedAt":3188},["ShallowReactive",2],{"navigation":3,"-docs-websocket":402,"-docs-websocket-surround":3183},[4,93,226,231,386,399],{"title":5,"path":6,"stem":7,"children":8,"icon":92},"","\u002Fdocs","1.docs\u002F1.index",[9,12,17,22,27,32,37,42,47,52,57,62,67,72,77,82,87],{"title":10,"path":6,"stem":7,"icon":11},"简介","i-lucide-compass",{"title":13,"path":14,"stem":15,"icon":16},"快速开始","\u002Fdocs\u002Fquick-start","1.docs\u002F2.quick-start","i-lucide-zap",{"title":18,"path":19,"stem":20,"icon":21},"Renderer","\u002Fdocs\u002Frenderer","1.docs\u002F4.renderer","ri:layout-masonry-line",{"title":23,"path":24,"stem":25,"icon":26},"路由","\u002Fdocs\u002Frouting","1.docs\u002F5.routing","ri:direction-line",{"title":28,"path":29,"stem":30,"icon":31},"资源","\u002Fdocs\u002Fassets","1.docs\u002F50.assets","ri:image-2-line",{"title":33,"path":34,"stem":35,"icon":36},"配置","\u002Fdocs\u002Fconfiguration","1.docs\u002F50.configuration","ri:settings-3-line",{"title":38,"path":39,"stem":40,"icon":41},"数据库","\u002Fdocs\u002Fdatabase","1.docs\u002F50.database","ri:database-2-line",{"title":43,"path":44,"stem":45,"icon":46},"生命周期","\u002Fdocs\u002Flifecycle","1.docs\u002F50.lifecycle","i-lucide-layers",{"title":48,"path":49,"stem":50,"icon":51},"OpenAPI","\u002Fdocs\u002Fopenapi","1.docs\u002F50.openapi","ri:contract-line",{"title":53,"path":54,"stem":55,"icon":56},"插件","\u002Fdocs\u002Fplugins","1.docs\u002F50.plugins","ri:plug-line",{"title":58,"path":59,"stem":60,"icon":61},"任务","\u002Fdocs\u002Ftasks","1.docs\u002F50.tasks","codicon:run-all",{"title":63,"path":64,"stem":65,"icon":66},"WebSocket","\u002Fdocs\u002Fwebsocket","1.docs\u002F50.websocket","ri:broadcast-fill",{"title":68,"path":69,"stem":70,"icon":71},"服务端入口","\u002Fdocs\u002Fserver-entry","1.docs\u002F6.server-entry","ri:server-line",{"title":73,"path":74,"stem":75,"icon":76},"缓存","\u002Fdocs\u002Fcache","1.docs\u002F7.cache","ri:speed-line",{"title":78,"path":79,"stem":80,"icon":81},"KV 存储","\u002Fdocs\u002Fstorage","1.docs\u002F8.storage","carbon:datastore",{"title":83,"path":84,"stem":85,"icon":86},"迁移指南","\u002Fdocs\u002Fmigration","1.docs\u002F99.migration","ri:arrow-right-up-line",{"title":88,"path":89,"stem":90,"icon":91},"每日构建通道","\u002Fdocs\u002Fnightly","1.docs\u002F99.nightly","ri:moon-fill","i-lucide-book-open",{"title":94,"path":95,"stem":96,"children":97,"icon":99},"部署","\u002Fdeploy","2.deploy\u002F0.index",[98,100,121],{"title":94,"path":95,"stem":96,"icon":99},"ri:upload-cloud-2-line",{"title":101,"path":102,"stem":103,"children":104,"page":120},"Runtimes","\u002Fdeploy\u002Fruntimes","2.deploy\u002F10.runtimes",[105,110,115],{"title":106,"path":107,"stem":108,"icon":109},"Node.js","\u002Fdeploy\u002Fruntimes\u002Fnode","2.deploy\u002F10.runtimes\u002F1.node","akar-icons:node-fill",{"title":111,"path":112,"stem":113,"icon":114},"Bun","\u002Fdeploy\u002Fruntimes\u002Fbun","2.deploy\u002F10.runtimes\u002Fbun","simple-icons:bun",{"title":116,"path":117,"stem":118,"icon":119},"Deno","\u002Fdeploy\u002Fruntimes\u002Fdeno","2.deploy\u002F10.runtimes\u002Fdeno","simple-icons:deno",false,{"title":122,"path":123,"stem":124,"children":125,"page":120},"Providers","\u002Fdeploy\u002Fproviders","2.deploy\u002F20.providers",[126,130,134,138,142,146,150,154,158,162,166,170,174,178,182,186,190,194,198,202,206,210,214,218,222],{"title":127,"path":128,"stem":129},"Alwaysdata","\u002Fdeploy\u002Fproviders\u002Falwaysdata","2.deploy\u002F20.providers\u002Falwaysdata",{"title":131,"path":132,"stem":133},"AWS Lambda","\u002Fdeploy\u002Fproviders\u002Faws","2.deploy\u002F20.providers\u002Faws",{"title":135,"path":136,"stem":137},"AWS Amplify","\u002Fdeploy\u002Fproviders\u002Faws-amplify","2.deploy\u002F20.providers\u002Faws-amplify",{"title":139,"path":140,"stem":141},"Azure","\u002Fdeploy\u002Fproviders\u002Fazure","2.deploy\u002F20.providers\u002Fazure",{"title":143,"path":144,"stem":145},"Cleavr","\u002Fdeploy\u002Fproviders\u002Fcleavr","2.deploy\u002F20.providers\u002Fcleavr",{"title":147,"path":148,"stem":149},"Cloudflare","\u002Fdeploy\u002Fproviders\u002Fcloudflare","2.deploy\u002F20.providers\u002Fcloudflare",{"title":151,"path":152,"stem":153},"Deno Deploy","\u002Fdeploy\u002Fproviders\u002Fdeno-deploy","2.deploy\u002F20.providers\u002Fdeno-deploy",{"title":155,"path":156,"stem":157},"DigitalOcean","\u002Fdeploy\u002Fproviders\u002Fdigitalocean","2.deploy\u002F20.providers\u002Fdigitalocean",{"title":159,"path":160,"stem":161},"EdgeOne Pages","\u002Fdeploy\u002Fproviders\u002Fedgeone","2.deploy\u002F20.providers\u002Fedgeone",{"title":163,"path":164,"stem":165},"Firebase","\u002Fdeploy\u002Fproviders\u002Ffirebase","2.deploy\u002F20.providers\u002Ffirebase",{"title":167,"path":168,"stem":169},"Flightcontrol","\u002Fdeploy\u002Fproviders\u002Fflightcontrol","2.deploy\u002F20.providers\u002Fflightcontrol",{"title":171,"path":172,"stem":173},"Genezio","\u002Fdeploy\u002Fproviders\u002Fgenezio","2.deploy\u002F20.providers\u002Fgenezio",{"title":175,"path":176,"stem":177},"GitHub Pages","\u002Fdeploy\u002Fproviders\u002Fgithub-pages","2.deploy\u002F20.providers\u002Fgithub-pages",{"title":179,"path":180,"stem":181},"GitLab Pages","\u002Fdeploy\u002Fproviders\u002Fgitlab-pages","2.deploy\u002F20.providers\u002Fgitlab-pages",{"title":183,"path":184,"stem":185},"Heroku","\u002Fdeploy\u002Fproviders\u002Fheroku","2.deploy\u002F20.providers\u002Fheroku",{"title":187,"path":188,"stem":189},"IIS","\u002Fdeploy\u002Fproviders\u002Fiis","2.deploy\u002F20.providers\u002Fiis",{"title":191,"path":192,"stem":193},"Koyeb","\u002Fdeploy\u002Fproviders\u002Fkoyeb","2.deploy\u002F20.providers\u002Fkoyeb",{"title":195,"path":196,"stem":197},"Netlify","\u002Fdeploy\u002Fproviders\u002Fnetlify","2.deploy\u002F20.providers\u002Fnetlify",{"title":199,"path":200,"stem":201},"Platform.sh","\u002Fdeploy\u002Fproviders\u002Fplatform-sh","2.deploy\u002F20.providers\u002Fplatform-sh",{"title":203,"path":204,"stem":205},"Render.com","\u002Fdeploy\u002Fproviders\u002Frender","2.deploy\u002F20.providers\u002Frender",{"title":207,"path":208,"stem":209},"StormKit","\u002Fdeploy\u002Fproviders\u002Fstormkit","2.deploy\u002F20.providers\u002Fstormkit",{"title":211,"path":212,"stem":213},"Vercel","\u002Fdeploy\u002Fproviders\u002Fvercel","2.deploy\u002F20.providers\u002Fvercel",{"title":215,"path":216,"stem":217},"Zeabur","\u002Fdeploy\u002Fproviders\u002Fzeabur","2.deploy\u002F20.providers\u002Fzeabur",{"title":219,"path":220,"stem":221},"Zephyr Cloud","\u002Fdeploy\u002Fproviders\u002Fzephyr","2.deploy\u002F20.providers\u002Fzephyr",{"title":223,"path":224,"stem":225},"Zerops","\u002Fdeploy\u002Fproviders\u002Fzerops","2.deploy\u002F20.providers\u002Fzerops",{"title":33,"path":227,"stem":228,"children":229,"icon":36},"\u002Fconfig","3.config\u002F0.index",[230],{"title":33,"path":227,"stem":228,"icon":36},{"title":232,"path":233,"stem":234,"children":235,"icon":237},"示例","\u002Fexamples","4.examples\u002F0.index",[236,238,243,248,253,258,262,267,272,277,282,287,292,296,301,305,309,314,319,324,329,334,339,344,349,354,358,363,368,372,377,382],{"title":232,"path":233,"stem":234,"icon":237},"i-lucide-folder-code",{"title":239,"path":240,"stem":241,"icon":242},"API 路由","\u002Fexamples\u002Fapi-routes","4.examples\u002Fapi-routes","i-lucide-route",{"title":244,"path":245,"stem":246,"icon":247},"自动导入","\u002Fexamples\u002Fauto-imports","4.examples\u002Fauto-imports","i-lucide-import",{"title":249,"path":250,"stem":251,"icon":252},"缓存处理器","\u002Fexamples\u002Fcached-handler","4.examples\u002Fcached-handler","i-lucide-clock",{"title":254,"path":255,"stem":256,"icon":257},"自定义错误处理器","\u002Fexamples\u002Fcustom-error-handler","4.examples\u002Fcustom-error-handler","i-lucide-alert-circle",{"title":38,"path":259,"stem":260,"icon":261},"\u002Fexamples\u002Fdatabase","4.examples\u002Fdatabase","i-lucide-database",{"title":263,"path":264,"stem":265,"icon":266},"Elysia","\u002Fexamples\u002Felysia","4.examples\u002Felysia","i-skill-icons-elysia-dark",{"title":268,"path":269,"stem":270,"icon":271},"Express","\u002Fexamples\u002Fexpress","4.examples\u002Fexpress","i-simple-icons-express",{"title":273,"path":274,"stem":275,"icon":276},"Fastify","\u002Fexamples\u002Ffastify","4.examples\u002Ffastify","i-simple-icons-fastify",{"title":278,"path":279,"stem":280,"icon":281},"你好世界","\u002Fexamples\u002Fhello-world","4.examples\u002Fhello-world","i-lucide-sparkles",{"title":283,"path":284,"stem":285,"icon":286},"Hono","\u002Fexamples\u002Fhono","4.examples\u002Fhono","i-logos-hono",{"title":288,"path":289,"stem":290,"icon":291},"导入别名","\u002Fexamples\u002Fimport-alias","4.examples\u002Fimport-alias","i-lucide-at-sign",{"title":293,"path":294,"stem":295,"icon":46},"中间件","\u002Fexamples\u002Fmiddleware","4.examples\u002Fmiddleware",{"title":297,"path":298,"stem":299,"icon":300},"Mono JSX","\u002Fexamples\u002Fmono-jsx","4.examples\u002Fmono-jsx","i-lucide-brackets",{"title":302,"path":303,"stem":304,"icon":300},"Nano JSX","\u002Fexamples\u002Fnano-jsx","4.examples\u002Fnano-jsx",{"title":53,"path":306,"stem":307,"icon":308},"\u002Fexamples\u002Fplugins","4.examples\u002Fplugins","i-lucide-plug",{"title":310,"path":311,"stem":312,"icon":313},"自定义渲染器","\u002Fexamples\u002Frenderer","4.examples\u002Frenderer","i-lucide-code",{"title":315,"path":316,"stem":317,"icon":318},"运行时配置","\u002Fexamples\u002Fruntime-config","4.examples\u002Fruntime-config","i-lucide-settings",{"title":320,"path":321,"stem":322,"icon":323},"服务端 Fetch","\u002Fexamples\u002Fserver-fetch","4.examples\u002Fserver-fetch","i-lucide-arrow-right-left",{"title":325,"path":326,"stem":327,"icon":328},"Shiki","\u002Fexamples\u002Fshiki","4.examples\u002Fshiki","i-lucide-highlighter",{"title":330,"path":331,"stem":332,"icon":333},"虚拟路由","\u002Fexamples\u002Fvirtual-routes","4.examples\u002Fvirtual-routes","i-lucide-box",{"title":335,"path":336,"stem":337,"icon":338},"Vite Nitro 插件","\u002Fexamples\u002Fvite-nitro-plugin","4.examples\u002Fvite-nitro-plugin","i-logos-vitejs",{"title":340,"path":341,"stem":342,"icon":343},"Vite RSC","\u002Fexamples\u002Fvite-rsc","4.examples\u002Fvite-rsc","i-logos-react",{"title":345,"path":346,"stem":347,"icon":348},"Vite SSR HTML","\u002Fexamples\u002Fvite-ssr-html","4.examples\u002Fvite-ssr-html","i-logos-html-5",{"title":350,"path":351,"stem":352,"icon":353},"使用 Preact 进行 SSR","\u002Fexamples\u002Fvite-ssr-preact","4.examples\u002Fvite-ssr-preact","i-logos-preact",{"title":355,"path":356,"stem":357,"icon":343},"使用 React 进行 SSR","\u002Fexamples\u002Fvite-ssr-react","4.examples\u002Fvite-ssr-react",{"title":359,"path":360,"stem":361,"icon":362},"SolidJS 服务端渲染","\u002Fexamples\u002Fvite-ssr-solid","4.examples\u002Fvite-ssr-solid","i-logos-solidjs-icon",{"title":364,"path":365,"stem":366,"icon":367},"使用 TanStack Router 的 SSR","\u002Fexamples\u002Fvite-ssr-tsr-react","4.examples\u002Fvite-ssr-tsr-react","i-simple-icons-tanstack",{"title":369,"path":370,"stem":371,"icon":367},"使用 TanStack Start 进行 SSR","\u002Fexamples\u002Fvite-ssr-tss-react","4.examples\u002Fvite-ssr-tss-react",{"title":373,"path":374,"stem":375,"icon":376},"基于 Vue Router 的 SSR","\u002Fexamples\u002Fvite-ssr-vue-router","4.examples\u002Fvite-ssr-vue-router","i-logos-vue",{"title":378,"path":379,"stem":380,"icon":381},"Vite + tRPC","\u002Fexamples\u002Fvite-trpc","4.examples\u002Fvite-trpc","i-simple-icons-trpc",{"title":63,"path":383,"stem":384,"icon":385},"\u002Fexamples\u002Fwebsocket","4.examples\u002Fwebsocket","i-lucide-radio",{"title":387,"path":388,"stem":389,"children":390},"Blog","\u002Fblog","9.blog",[391,395],{"title":392,"path":388,"stem":393,"icon":394},"博客","9.blog\u002Findex","i-lucide-file-text",{"title":396,"path":397,"stem":398,"icon":394},"Nitro v3 测试版已发布！","\u002Fblog\u002Fv3-beta","9.blog\u002F1.v3-beta",{"title":5,"path":400,"stem":401},"\u002F","index",{"id":403,"title":63,"body":404,"description":3177,"extension":3178,"meta":3179,"navigation":3180,"path":64,"seo":3181,"stem":65,"__hash__":3182},"content\u002F1.docs\u002F50.websocket.md",{"type":405,"value":406,"toc":3153,"icon":66},"minimark",[407,411,416,421,424,514,517,529,737,751,755,765,900,903,906,911,914,1109,1114,1186,1193,1198,1201,1232,1236,1239,1289,1294,1307,1355,1359,1362,1391,1394,1402,1404,1534,1537,1544,1547,1585,1591,1594,1613,1619,1622,1640,1646,1654,1684,1690,1693,1716,1722,1725,1729,1737,1826,1907,1911,1914,2136,2152,2155,2161,2169,2351,2362,2371,2622,2626,2634,2828,2837,2901,2904,2916,3145,3149],[408,409,410],"p",{},"WebSocket 可以在客户端与服务器之间实现实时双向通信。Nitro 的 WebSocket 集成适用于所有受支持的部署目标，包括 Node.js、Bun、Deno 以及 Cloudflare Workers。",[412,413],"read-more",{"title":414,"to":415},"CrossWS Documentation","https:\u002F\u002Fcrossws.h3.dev\u002F",[417,418,420],"h2",{"id":419},"启用-websocket","启用 WebSocket",[408,422,423],{},"在 Nitro 配置中启用 WebSocket 支持：",[425,426,427],"code-group",{},[428,429,434],"pre",{"className":430,"code":431,"filename":432,"language":433,"meta":5,"style":5},"language-ts shiki shiki-themes github-light github-dark github-dark","import { defineConfig } from \"nitro\";\n\nexport default defineConfig({\n  features: {\n    websocket: true,\n  },\n});\n","nitro.config.ts","ts",[435,436,437,460,467,483,489,502,508],"code",{"__ignoreMap":5},[438,439,442,446,450,453,457],"span",{"class":440,"line":441},"line",1,[438,443,445],{"class":444},"so5gQ","import",[438,447,449],{"class":448},"slsVL"," { defineConfig } ",[438,451,452],{"class":444},"from",[438,454,456],{"class":455},"sfrk1"," \"nitro\"",[438,458,459],{"class":448},";\n",[438,461,463],{"class":440,"line":462},2,[438,464,466],{"emptyLinePlaceholder":465},true,"\n",[438,468,470,473,476,480],{"class":440,"line":469},3,[438,471,472],{"class":444},"export",[438,474,475],{"class":444}," default",[438,477,479],{"class":478},"shcOC"," defineConfig",[438,481,482],{"class":448},"({\n",[438,484,486],{"class":440,"line":485},4,[438,487,488],{"class":448},"  features: {\n",[438,490,492,495,499],{"class":440,"line":491},5,[438,493,494],{"class":448},"    websocket: ",[438,496,498],{"class":497},"suiK_","true",[438,500,501],{"class":448},",\n",[438,503,505],{"class":440,"line":504},6,[438,506,507],{"class":448},"  },\n",[438,509,511],{"class":440,"line":510},7,[438,512,513],{"class":448},"});\n",[417,515,516],{"id":516},"用法",[408,518,519,520,523,524,528],{},"使用 ",[435,521,522],{},"defineWebSocketHandler"," 创建一个 WebSocket 处理器，并从路由文件中导出。WebSocket 处理器与普通请求处理器一样，遵循相同的",[525,526,527],"a",{"href":24},"文件路由","规则。",[428,530,533],{"className":430,"code":531,"filename":532,"language":433,"meta":5,"style":5},"import { defineWebSocketHandler } from \"nitro\";\n\nexport default defineWebSocketHandler({\n  open(peer) {\n    console.log(\"已连接：\", peer.id);\n  },\n  message(peer, message) {\n    console.log(\"收到消息：\", message.text());\n    peer.send(\"来自服务器的问候！\");\n  },\n  close(peer, details) {\n    console.log(\"已断开：\", peer.id, details.code, details.reason);\n  },\n  error(peer, error) {\n    console.error(\"错误：\", error);\n  },\n});\n","routes\u002F_ws.ts",[435,534,535,548,552,563,578,594,598,615,636,653,658,675,690,695,712,727,732],{"__ignoreMap":5},[438,536,537,539,542,544,546],{"class":440,"line":441},[438,538,445],{"class":444},[438,540,541],{"class":448}," { defineWebSocketHandler } ",[438,543,452],{"class":444},[438,545,456],{"class":455},[438,547,459],{"class":448},[438,549,550],{"class":440,"line":462},[438,551,466],{"emptyLinePlaceholder":465},[438,553,554,556,558,561],{"class":440,"line":469},[438,555,472],{"class":444},[438,557,475],{"class":444},[438,559,560],{"class":478}," defineWebSocketHandler",[438,562,482],{"class":448},[438,564,565,568,571,575],{"class":440,"line":485},[438,566,567],{"class":478},"  open",[438,569,570],{"class":448},"(",[438,572,574],{"class":573},"sQHwn","peer",[438,576,577],{"class":448},") {\n",[438,579,580,583,586,588,591],{"class":440,"line":491},[438,581,582],{"class":448},"    console.",[438,584,585],{"class":478},"log",[438,587,570],{"class":448},[438,589,590],{"class":455},"\"已连接：\"",[438,592,593],{"class":448},", peer.id);\n",[438,595,596],{"class":440,"line":504},[438,597,507],{"class":448},[438,599,600,603,605,607,610,613],{"class":440,"line":510},[438,601,602],{"class":478},"  message",[438,604,570],{"class":448},[438,606,574],{"class":573},[438,608,609],{"class":448},", ",[438,611,612],{"class":573},"message",[438,614,577],{"class":448},[438,616,618,620,622,624,627,630,633],{"class":440,"line":617},8,[438,619,582],{"class":448},[438,621,585],{"class":478},[438,623,570],{"class":448},[438,625,626],{"class":455},"\"收到消息：\"",[438,628,629],{"class":448},", message.",[438,631,632],{"class":478},"text",[438,634,635],{"class":448},"());\n",[438,637,639,642,645,647,650],{"class":440,"line":638},9,[438,640,641],{"class":448},"    peer.",[438,643,644],{"class":478},"send",[438,646,570],{"class":448},[438,648,649],{"class":455},"\"来自服务器的问候！\"",[438,651,652],{"class":448},");\n",[438,654,656],{"class":440,"line":655},10,[438,657,507],{"class":448},[438,659,661,664,666,668,670,673],{"class":440,"line":660},11,[438,662,663],{"class":478},"  close",[438,665,570],{"class":448},[438,667,574],{"class":573},[438,669,609],{"class":448},[438,671,672],{"class":573},"details",[438,674,577],{"class":448},[438,676,678,680,682,684,687],{"class":440,"line":677},12,[438,679,582],{"class":448},[438,681,585],{"class":478},[438,683,570],{"class":448},[438,685,686],{"class":455},"\"已断开：\"",[438,688,689],{"class":448},", peer.id, details.code, details.reason);\n",[438,691,693],{"class":440,"line":692},13,[438,694,507],{"class":448},[438,696,698,701,703,705,707,710],{"class":440,"line":697},14,[438,699,700],{"class":478},"  error",[438,702,570],{"class":448},[438,704,574],{"class":573},[438,706,609],{"class":448},[438,708,709],{"class":573},"error",[438,711,577],{"class":448},[438,713,715,717,719,721,724],{"class":440,"line":714},15,[438,716,582],{"class":448},[438,718,709],{"class":478},[438,720,570],{"class":448},[438,722,723],{"class":455},"\"错误：\"",[438,725,726],{"class":448},", error);\n",[438,728,730],{"class":440,"line":729},16,[438,731,507],{"class":448},[438,733,735],{"class":440,"line":734},17,[438,736,513],{"class":448},[738,739,740],"tip",{},[408,741,742,743,746,747,750],{},"你可以为 WebSocket 处理器使用任意路由路径。例如，",[435,744,745],{},"routes\u002Fchat.ts"," 会处理 ",[435,748,749],{},"\u002Fchat"," 上的 WebSocket 连接。",[752,753,754],"h3",{"id":754},"从客户端连接",[408,756,757,758,764],{},"使用浏览器的 ",[525,759,763],{"href":760,"rel":761},"https:\u002F\u002Fdeveloper.mozilla.org\u002Fen-US\u002Fdocs\u002FWeb\u002FAPI\u002FWebSocket",[762],"nofollow","WebSocket API"," 进行连接：",[428,766,770],{"className":767,"code":768,"language":769,"meta":5,"style":5},"language-js shiki shiki-themes github-light github-dark github-dark","const ws = new WebSocket(\"ws:\u002F\u002Flocalhost:3000\u002F_ws\");\n\nws.addEventListener(\"open\", () => {\n  console.log(\"已连接！\");\n  ws.send(\"来自客户端的问候！\");\n});\n\nws.addEventListener(\"message\", (event) => {\n  console.log(\"收到：\", event.data);\n});\n","js",[435,771,772,796,800,822,836,850,854,858,882,896],{"__ignoreMap":5},[438,773,774,777,780,783,786,789,791,794],{"class":440,"line":441},[438,775,776],{"class":444},"const",[438,778,779],{"class":497}," ws",[438,781,782],{"class":444}," =",[438,784,785],{"class":444}," new",[438,787,788],{"class":478}," WebSocket",[438,790,570],{"class":448},[438,792,793],{"class":455},"\"ws:\u002F\u002Flocalhost:3000\u002F_ws\"",[438,795,652],{"class":448},[438,797,798],{"class":440,"line":462},[438,799,466],{"emptyLinePlaceholder":465},[438,801,802,805,808,810,813,816,819],{"class":440,"line":469},[438,803,804],{"class":448},"ws.",[438,806,807],{"class":478},"addEventListener",[438,809,570],{"class":448},[438,811,812],{"class":455},"\"open\"",[438,814,815],{"class":448},", () ",[438,817,818],{"class":444},"=>",[438,820,821],{"class":448}," {\n",[438,823,824,827,829,831,834],{"class":440,"line":485},[438,825,826],{"class":448},"  console.",[438,828,585],{"class":478},[438,830,570],{"class":448},[438,832,833],{"class":455},"\"已连接！\"",[438,835,652],{"class":448},[438,837,838,841,843,845,848],{"class":440,"line":491},[438,839,840],{"class":448},"  ws.",[438,842,644],{"class":478},[438,844,570],{"class":448},[438,846,847],{"class":455},"\"来自客户端的问候！\"",[438,849,652],{"class":448},[438,851,852],{"class":440,"line":504},[438,853,513],{"class":448},[438,855,856],{"class":440,"line":510},[438,857,466],{"emptyLinePlaceholder":465},[438,859,860,862,864,866,869,872,875,878,880],{"class":440,"line":617},[438,861,804],{"class":448},[438,863,807],{"class":478},[438,865,570],{"class":448},[438,867,868],{"class":455},"\"message\"",[438,870,871],{"class":448},", (",[438,873,874],{"class":573},"event",[438,876,877],{"class":448},") ",[438,879,818],{"class":444},[438,881,821],{"class":448},[438,883,884,886,888,890,893],{"class":440,"line":638},[438,885,826],{"class":448},[438,887,585],{"class":478},[438,889,570],{"class":448},[438,891,892],{"class":455},"\"收到：\"",[438,894,895],{"class":448},", event.data);\n",[438,897,898],{"class":440,"line":655},[438,899,513],{"class":448},[417,901,902],{"id":902},"钩子",[408,904,905],{},"WebSocket 处理器支持以下生命周期钩子：",[752,907,909],{"id":908},"upgrade",[435,910,908],{},[408,912,913],{},"在 WebSocket 连接建立之前调用。你可以用它来校验请求、设置命名空间，或给 peer 附加上下文数据。",[428,915,917],{"className":430,"code":916,"filename":745,"language":433,"meta":5,"style":5},"import { defineWebSocketHandler } from \"nitro\";\n\nexport default defineWebSocketHandler({\n  upgrade(request) {\n    const url = new URL(request.url);\n    const token = url.searchParams.get(\"token\");\n    if (!isValidToken(token)) {\n      throw new Response(\"未授权\", { status: 401 });\n    }\n    return {\n      context: { userId: getUserId(token) },\n    };\n  },\n  open(peer) {\n    console.log(\"用户已连接：\", peer.context.userId);\n  },\n  \u002F\u002F ...\n});\n",[435,918,919,931,935,945,957,975,997,1014,1038,1043,1050,1061,1066,1070,1080,1094,1098,1104],{"__ignoreMap":5},[438,920,921,923,925,927,929],{"class":440,"line":441},[438,922,445],{"class":444},[438,924,541],{"class":448},[438,926,452],{"class":444},[438,928,456],{"class":455},[438,930,459],{"class":448},[438,932,933],{"class":440,"line":462},[438,934,466],{"emptyLinePlaceholder":465},[438,936,937,939,941,943],{"class":440,"line":469},[438,938,472],{"class":444},[438,940,475],{"class":444},[438,942,560],{"class":478},[438,944,482],{"class":448},[438,946,947,950,952,955],{"class":440,"line":485},[438,948,949],{"class":478},"  upgrade",[438,951,570],{"class":448},[438,953,954],{"class":573},"request",[438,956,577],{"class":448},[438,958,959,962,965,967,969,972],{"class":440,"line":491},[438,960,961],{"class":444},"    const",[438,963,964],{"class":497}," url",[438,966,782],{"class":444},[438,968,785],{"class":444},[438,970,971],{"class":478}," URL",[438,973,974],{"class":448},"(request.url);\n",[438,976,977,979,982,984,987,990,992,995],{"class":440,"line":504},[438,978,961],{"class":444},[438,980,981],{"class":497}," token",[438,983,782],{"class":444},[438,985,986],{"class":448}," url.searchParams.",[438,988,989],{"class":478},"get",[438,991,570],{"class":448},[438,993,994],{"class":455},"\"token\"",[438,996,652],{"class":448},[438,998,999,1002,1005,1008,1011],{"class":440,"line":510},[438,1000,1001],{"class":444},"    if",[438,1003,1004],{"class":448}," (",[438,1006,1007],{"class":444},"!",[438,1009,1010],{"class":478},"isValidToken",[438,1012,1013],{"class":448},"(token)) {\n",[438,1015,1016,1019,1021,1024,1026,1029,1032,1035],{"class":440,"line":617},[438,1017,1018],{"class":444},"      throw",[438,1020,785],{"class":444},[438,1022,1023],{"class":478}," Response",[438,1025,570],{"class":448},[438,1027,1028],{"class":455},"\"未授权\"",[438,1030,1031],{"class":448},", { status: ",[438,1033,1034],{"class":497},"401",[438,1036,1037],{"class":448}," });\n",[438,1039,1040],{"class":440,"line":638},[438,1041,1042],{"class":448},"    }\n",[438,1044,1045,1048],{"class":440,"line":655},[438,1046,1047],{"class":444},"    return",[438,1049,821],{"class":448},[438,1051,1052,1055,1058],{"class":440,"line":660},[438,1053,1054],{"class":448},"      context: { userId: ",[438,1056,1057],{"class":478},"getUserId",[438,1059,1060],{"class":448},"(token) },\n",[438,1062,1063],{"class":440,"line":677},[438,1064,1065],{"class":448},"    };\n",[438,1067,1068],{"class":440,"line":692},[438,1069,507],{"class":448},[438,1071,1072,1074,1076,1078],{"class":440,"line":697},[438,1073,567],{"class":478},[438,1075,570],{"class":448},[438,1077,574],{"class":573},[438,1079,577],{"class":448},[438,1081,1082,1084,1086,1088,1091],{"class":440,"line":714},[438,1083,582],{"class":448},[438,1085,585],{"class":478},[438,1087,570],{"class":448},[438,1089,1090],{"class":455},"\"用户已连接：\"",[438,1092,1093],{"class":448},", peer.context.userId);\n",[438,1095,1096],{"class":440,"line":729},[438,1097,507],{"class":448},[438,1099,1100],{"class":440,"line":734},[438,1101,1103],{"class":1102},"sCsY4","  \u002F\u002F ...\n",[438,1105,1107],{"class":440,"line":1106},18,[438,1108,513],{"class":448},[408,1110,1111,1113],{},[435,1112,908],{}," 钩子可以返回一个对象，包含：",[1115,1116,1117,1133],"table",{},[1118,1119,1120],"thead",{},[1121,1122,1123,1127,1130],"tr",{},[1124,1125,1126],"th",{},"属性",[1124,1128,1129],{},"类型",[1124,1131,1132],{},"说明",[1134,1135,1136,1152,1167],"tbody",{},[1121,1137,1138,1144,1149],{},[1139,1140,1141],"td",{},[435,1142,1143],{},"headers",[1139,1145,1146],{},[435,1147,1148],{},"HeadersInit",[1139,1150,1151],{},"要包含在升级响应中的响应头",[1121,1153,1154,1159,1164],{},[1139,1155,1156],{},[435,1157,1158],{},"namespace",[1139,1160,1161],{},[435,1162,1163],{},"string",[1139,1165,1166],{},"覆盖此连接的发布\u002F订阅命名空间",[1121,1168,1169,1174,1179],{},[1139,1170,1171],{},[435,1172,1173],{},"context",[1139,1175,1176],{},[435,1177,1178],{},"object",[1139,1180,1181,1182,1185],{},"附加到 ",[435,1183,1184],{},"peer.context"," 的数据",[408,1187,1188,1189,1192],{},"抛出一个 ",[435,1190,1191],{},"Response"," 即可拒绝升级请求。",[752,1194,1196],{"id":1195},"open",[435,1197,1195],{},[408,1199,1200],{},"当 WebSocket 连接建立完成，且 peer 已可收发消息时调用。",[428,1202,1204],{"className":430,"code":1203,"language":433,"meta":5,"style":5},"open(peer) {\n  peer.send(\"欢迎！\");\n}\n",[435,1205,1206,1213,1227],{"__ignoreMap":5},[438,1207,1208,1210],{"class":440,"line":441},[438,1209,1195],{"class":478},[438,1211,1212],{"class":448},"(peer) {\n",[438,1214,1215,1218,1220,1222,1225],{"class":440,"line":462},[438,1216,1217],{"class":448},"  peer.",[438,1219,644],{"class":478},[438,1221,570],{"class":448},[438,1223,1224],{"class":455},"\"欢迎！\"",[438,1226,652],{"class":448},[438,1228,1229],{"class":440,"line":469},[438,1230,1231],{"class":448},"}\n",[752,1233,1234],{"id":612},[435,1235,612],{},[408,1237,1238],{},"在收到 peer 发来的消息时调用。",[428,1240,1242],{"className":430,"code":1241,"language":433,"meta":5,"style":5},"message(peer, message) {\n  const text = message.text();\n  const data = message.json();\n}\n",[435,1243,1244,1251,1269,1285],{"__ignoreMap":5},[438,1245,1246,1248],{"class":440,"line":441},[438,1247,612],{"class":478},[438,1249,1250],{"class":448},"(peer, message) {\n",[438,1252,1253,1256,1259,1261,1264,1266],{"class":440,"line":462},[438,1254,1255],{"class":444},"  const",[438,1257,1258],{"class":497}," text",[438,1260,782],{"class":444},[438,1262,1263],{"class":448}," message.",[438,1265,632],{"class":478},[438,1267,1268],{"class":448},"();\n",[438,1270,1271,1273,1276,1278,1280,1283],{"class":440,"line":469},[438,1272,1255],{"class":444},[438,1274,1275],{"class":497}," data",[438,1277,782],{"class":444},[438,1279,1263],{"class":448},[438,1281,1282],{"class":478},"json",[438,1284,1268],{"class":448},[438,1286,1287],{"class":440,"line":485},[438,1288,1231],{"class":448},[752,1290,1292],{"id":1291},"close",[435,1293,1291],{},[408,1295,1296,1297,1299,1300,1302,1303,1306],{},"当 WebSocket 连接关闭时调用。会收到一个 ",[435,1298,672],{}," 对象，其中可能包含 ",[435,1301,435],{}," 和 ",[435,1304,1305],{},"reason","。",[428,1308,1310],{"className":430,"code":1309,"language":433,"meta":5,"style":5},"close(peer, details) {\n  console.log(`已关闭：${details.code} - ${details.reason}`);\n}\n",[435,1311,1312,1319,1351],{"__ignoreMap":5},[438,1313,1314,1316],{"class":440,"line":441},[438,1315,1291],{"class":478},[438,1317,1318],{"class":448},"(peer, details) {\n",[438,1320,1321,1323,1325,1327,1330,1332,1335,1337,1340,1342,1344,1346,1349],{"class":440,"line":462},[438,1322,826],{"class":448},[438,1324,585],{"class":478},[438,1326,570],{"class":448},[438,1328,1329],{"class":455},"`已关闭：${",[438,1331,672],{"class":448},[438,1333,1334],{"class":455},".",[438,1336,435],{"class":448},[438,1338,1339],{"class":455},"} - ${",[438,1341,672],{"class":448},[438,1343,1334],{"class":455},[438,1345,1305],{"class":448},[438,1347,1348],{"class":455},"}`",[438,1350,652],{"class":448},[438,1352,1353],{"class":440,"line":469},[438,1354,1231],{"class":448},[752,1356,1357],{"id":709},[435,1358,709],{},[408,1360,1361],{},"在 WebSocket 连接发生错误时调用。",[428,1363,1365],{"className":430,"code":1364,"language":433,"meta":5,"style":5},"error(peer, error) {\n  console.error(\"WebSocket 错误：\", error);\n}\n",[435,1366,1367,1374,1387],{"__ignoreMap":5},[438,1368,1369,1371],{"class":440,"line":441},[438,1370,709],{"class":478},[438,1372,1373],{"class":448},"(peer, error) {\n",[438,1375,1376,1378,1380,1382,1385],{"class":440,"line":462},[438,1377,826],{"class":448},[438,1379,709],{"class":478},[438,1381,570],{"class":448},[438,1383,1384],{"class":455},"\"WebSocket 错误：\"",[438,1386,726],{"class":448},[438,1388,1389],{"class":440,"line":469},[438,1390,1231],{"class":448},[417,1392,1393],{"id":574},"Peer",[408,1395,1396,1398,1399,1401],{},[435,1397,574],{}," 对象表示一个已连接的 WebSocket 客户端。除 ",[435,1400,908],{}," 外，其他所有钩子中都可以访问它。",[752,1403,1126],{"id":1126},[1115,1405,1406,1416],{},[1118,1407,1408],{},[1121,1409,1410,1412,1414],{},[1124,1411,1126],{},[1124,1413,1129],{},[1124,1415,1132],{},[1134,1417,1418,1432,1445,1461,1475,1490,1505,1520],{},[1121,1419,1420,1425,1429],{},[1139,1421,1422],{},[435,1423,1424],{},"id",[1139,1426,1427],{},[435,1428,1163],{},[1139,1430,1431],{},"当前 peer 的唯一标识",[1121,1433,1434,1438,1442],{},[1139,1435,1436],{},[435,1437,1158],{},[1139,1439,1440],{},[435,1441,1163],{},[1139,1443,1444],{},"当前 peer 所属的发布\u002F订阅命名空间",[1121,1446,1447,1451,1455],{},[1139,1448,1449],{},[435,1450,1173],{},[1139,1452,1453],{},[435,1454,1178],{},[1139,1456,1457,1458,1460],{},"在 ",[435,1459,908],{}," 阶段设置的任意上下文数据",[1121,1462,1463,1467,1472],{},[1139,1464,1465],{},[435,1466,954],{},[1139,1468,1469],{},[435,1470,1471],{},"Request",[1139,1473,1474],{},"原始升级请求",[1121,1476,1477,1482,1487],{},[1139,1478,1479],{},[435,1480,1481],{},"peers",[1139,1483,1484],{},[435,1485,1486],{},"Set\u003CPeer>",[1139,1488,1489],{},"同一命名空间下的所有已连接 peer",[1121,1491,1492,1497,1502],{},[1139,1493,1494],{},[435,1495,1496],{},"topics",[1139,1498,1499],{},[435,1500,1501],{},"Set\u003Cstring>",[1139,1503,1504],{},"当前 peer 订阅的主题",[1121,1506,1507,1512,1517],{},[1139,1508,1509],{},[435,1510,1511],{},"remoteAddress",[1139,1513,1514],{},[435,1515,1516],{},"string?",[1139,1518,1519],{},"客户端 IP 地址（取决于适配器）",[1121,1521,1522,1527,1531],{},[1139,1523,1524],{},[435,1525,1526],{},"websocket",[1139,1528,1529],{},[435,1530,63],{},[1139,1532,1533],{},"底层的 WebSocket 实例",[752,1535,1536],{"id":1536},"方法",[1538,1539,1541],"h4",{"id":1540},"peersenddata-options",[435,1542,1543],{},"peer.send(data, options?)",[408,1545,1546],{},"直接向当前 peer 发送消息。支持字符串、对象（会序列化为 JSON）以及二进制数据。",[428,1548,1550],{"className":430,"code":1549,"language":433,"meta":5,"style":5},"peer.send(\"你好！\");\npeer.send({ type: \"greeting\", text: \"你好！\" });\n",[435,1551,1552,1566],{"__ignoreMap":5},[438,1553,1554,1557,1559,1561,1564],{"class":440,"line":441},[438,1555,1556],{"class":448},"peer.",[438,1558,644],{"class":478},[438,1560,570],{"class":448},[438,1562,1563],{"class":455},"\"你好！\"",[438,1565,652],{"class":448},[438,1567,1568,1570,1572,1575,1578,1581,1583],{"class":440,"line":462},[438,1569,1556],{"class":448},[438,1571,644],{"class":478},[438,1573,1574],{"class":448},"({ type: ",[438,1576,1577],{"class":455},"\"greeting\"",[438,1579,1580],{"class":448},", text: ",[438,1582,1563],{"class":455},[438,1584,1037],{"class":448},[1538,1586,1588],{"id":1587},"peersubscribetopic",[435,1589,1590],{},"peer.subscribe(topic)",[408,1592,1593],{},"让当前 peer 订阅一个发布\u002F订阅主题。",[428,1595,1597],{"className":430,"code":1596,"language":433,"meta":5,"style":5},"peer.subscribe(\"notifications\");\n",[435,1598,1599],{"__ignoreMap":5},[438,1600,1601,1603,1606,1608,1611],{"class":440,"line":441},[438,1602,1556],{"class":448},[438,1604,1605],{"class":478},"subscribe",[438,1607,570],{"class":448},[438,1609,1610],{"class":455},"\"notifications\"",[438,1612,652],{"class":448},[1538,1614,1616],{"id":1615},"peerunsubscribetopic",[435,1617,1618],{},"peer.unsubscribe(topic)",[408,1620,1621],{},"取消当前 peer 对某个主题的订阅。",[428,1623,1625],{"className":430,"code":1624,"language":433,"meta":5,"style":5},"peer.unsubscribe(\"notifications\");\n",[435,1626,1627],{"__ignoreMap":5},[438,1628,1629,1631,1634,1636,1638],{"class":440,"line":441},[438,1630,1556],{"class":448},[438,1632,1633],{"class":478},"unsubscribe",[438,1635,570],{"class":448},[438,1637,1610],{"class":455},[438,1639,652],{"class":448},[1538,1641,1643],{"id":1642},"peerpublishtopic-data-options",[435,1644,1645],{},"peer.publish(topic, data, options?)",[408,1647,1648,1649,1653],{},"向同一命名空间内订阅了该主题的所有 peer 广播消息。发送消息的 peer ",[1650,1651,1652],"strong",{},"不会","收到这条消息。",[428,1655,1657],{"className":430,"code":1656,"language":433,"meta":5,"style":5},"peer.publish(\"chat\", { user: \"小明\", text: \"大家好！\" });\n",[435,1658,1659],{"__ignoreMap":5},[438,1660,1661,1663,1666,1668,1671,1674,1677,1679,1682],{"class":440,"line":441},[438,1662,1556],{"class":448},[438,1664,1665],{"class":478},"publish",[438,1667,570],{"class":448},[438,1669,1670],{"class":455},"\"chat\"",[438,1672,1673],{"class":448},", { user: ",[438,1675,1676],{"class":455},"\"小明\"",[438,1678,1580],{"class":448},[438,1680,1681],{"class":455},"\"大家好！\"",[438,1683,1037],{"class":448},[1538,1685,1687],{"id":1686},"peerclosecode-reason",[435,1688,1689],{},"peer.close(code?, reason?)",[408,1691,1692],{},"优雅地关闭 WebSocket 连接。",[428,1694,1696],{"className":430,"code":1695,"language":433,"meta":5,"style":5},"peer.close(1000, \"正常关闭\");\n",[435,1697,1698],{"__ignoreMap":5},[438,1699,1700,1702,1704,1706,1709,1711,1714],{"class":440,"line":441},[438,1701,1556],{"class":448},[438,1703,1291],{"class":478},[438,1705,570],{"class":448},[438,1707,1708],{"class":497},"1000",[438,1710,609],{"class":448},[438,1712,1713],{"class":455},"\"正常关闭\"",[438,1715,652],{"class":448},[1538,1717,1719],{"id":1718},"peerterminate",[435,1720,1721],{},"peer.terminate()",[408,1723,1724],{},"立即终止连接，不发送关闭帧。",[417,1726,1728],{"id":1727},"message-1","Message",[408,1730,1731,1733,1734,1736],{},[435,1732,612],{}," 钩子中的 ",[435,1735,612],{}," 对象提供了多种方法，用于以不同格式读取传入数据。",[1115,1738,1739,1750],{},[1118,1740,1741],{},[1121,1742,1743,1745,1748],{},[1124,1744,1536],{},[1124,1746,1747],{},"返回类型",[1124,1749,1132],{},[1134,1751,1752,1766,1781,1796,1811],{},[1121,1753,1754,1759,1763],{},[1139,1755,1756],{},[435,1757,1758],{},"text()",[1139,1760,1761],{},[435,1762,1163],{},[1139,1764,1765],{},"将消息作为 UTF-8 字符串读取",[1121,1767,1768,1773,1778],{},[1139,1769,1770],{},[435,1771,1772],{},"json()",[1139,1774,1775],{},[435,1776,1777],{},"T",[1139,1779,1780],{},"将消息解析为 JSON",[1121,1782,1783,1788,1793],{},[1139,1784,1785],{},[435,1786,1787],{},"uint8Array()",[1139,1789,1790],{},[435,1791,1792],{},"Uint8Array",[1139,1794,1795],{},"将消息读取为字节数组",[1121,1797,1798,1803,1808],{},[1139,1799,1800],{},[435,1801,1802],{},"arrayBuffer()",[1139,1804,1805],{},[435,1806,1807],{},"ArrayBuffer",[1139,1809,1810],{},"将消息读取为 ArrayBuffer",[1121,1812,1813,1818,1823],{},[1139,1814,1815],{},[435,1816,1817],{},"blob()",[1139,1819,1820],{},[435,1821,1822],{},"Blob",[1139,1824,1825],{},"将消息读取为 Blob",[428,1827,1829],{"className":430,"code":1828,"language":433,"meta":5,"style":5},"message(peer, message) {\n  \u002F\u002F 按文本解析\n  const text = message.text();\n\n  \u002F\u002F 按带类型的 JSON 解析\n  const data = message.json\u003C{ type: string; payload: unknown }>();\n}\n",[435,1830,1831,1837,1842,1856,1860,1865,1903],{"__ignoreMap":5},[438,1832,1833,1835],{"class":440,"line":441},[438,1834,612],{"class":478},[438,1836,1250],{"class":448},[438,1838,1839],{"class":440,"line":462},[438,1840,1841],{"class":1102},"  \u002F\u002F 按文本解析\n",[438,1843,1844,1846,1848,1850,1852,1854],{"class":440,"line":469},[438,1845,1255],{"class":444},[438,1847,1258],{"class":497},[438,1849,782],{"class":444},[438,1851,1263],{"class":448},[438,1853,632],{"class":478},[438,1855,1268],{"class":448},[438,1857,1858],{"class":440,"line":485},[438,1859,466],{"emptyLinePlaceholder":465},[438,1861,1862],{"class":440,"line":491},[438,1863,1864],{"class":1102},"  \u002F\u002F 按带类型的 JSON 解析\n",[438,1866,1867,1869,1871,1873,1875,1877,1880,1883,1886,1889,1892,1895,1897,1900],{"class":440,"line":504},[438,1868,1255],{"class":444},[438,1870,1275],{"class":497},[438,1872,782],{"class":444},[438,1874,1263],{"class":448},[438,1876,1282],{"class":478},[438,1878,1879],{"class":448},"\u003C{ ",[438,1881,1882],{"class":573},"type",[438,1884,1885],{"class":444},":",[438,1887,1888],{"class":497}," string",[438,1890,1891],{"class":448},"; ",[438,1893,1894],{"class":573},"payload",[438,1896,1885],{"class":444},[438,1898,1899],{"class":497}," unknown",[438,1901,1902],{"class":448}," }>();\n",[438,1904,1905],{"class":440,"line":510},[438,1906,1231],{"class":448},[417,1908,1910],{"id":1909},"发布订阅","发布\u002F订阅",[408,1912,1913],{},"发布\u002F订阅（pub\u002Fsub）允许你通过主题向一组已连接的 peer 广播消息。peer 订阅主题后，就能收到发布到这些主题的消息。",[428,1915,1917],{"className":430,"code":1916,"filename":745,"language":433,"meta":5,"style":5},"import { defineWebSocketHandler } from \"nitro\";\n\nexport default defineWebSocketHandler({\n  open(peer) {\n    peer.subscribe(\"chat\");\n    peer.publish(\"chat\", { system: `${peer} 加入了聊天室` });\n    peer.send({ system: \"欢迎来到聊天室！\" });\n  },\n  message(peer, message) {\n    \u002F\u002F 广播给其他所有订阅者\n    peer.publish(\"chat\", {\n      user: peer.toString(),\n      text: message.text(),\n    });\n    \u002F\u002F 回显给发送者\n    peer.send({ user: \"你\", text: message.text() });\n  },\n  close(peer) {\n    peer.publish(\"chat\", { system: `${peer} 离开了聊天室` });\n  },\n});\n",[435,1918,1919,1931,1935,1945,1955,1967,1990,2004,2008,2022,2027,2040,2051,2060,2065,2070,2090,2094,2104,2126,2131],{"__ignoreMap":5},[438,1920,1921,1923,1925,1927,1929],{"class":440,"line":441},[438,1922,445],{"class":444},[438,1924,541],{"class":448},[438,1926,452],{"class":444},[438,1928,456],{"class":455},[438,1930,459],{"class":448},[438,1932,1933],{"class":440,"line":462},[438,1934,466],{"emptyLinePlaceholder":465},[438,1936,1937,1939,1941,1943],{"class":440,"line":469},[438,1938,472],{"class":444},[438,1940,475],{"class":444},[438,1942,560],{"class":478},[438,1944,482],{"class":448},[438,1946,1947,1949,1951,1953],{"class":440,"line":485},[438,1948,567],{"class":478},[438,1950,570],{"class":448},[438,1952,574],{"class":573},[438,1954,577],{"class":448},[438,1956,1957,1959,1961,1963,1965],{"class":440,"line":491},[438,1958,641],{"class":448},[438,1960,1605],{"class":478},[438,1962,570],{"class":448},[438,1964,1670],{"class":455},[438,1966,652],{"class":448},[438,1968,1969,1971,1973,1975,1977,1980,1983,1985,1988],{"class":440,"line":504},[438,1970,641],{"class":448},[438,1972,1665],{"class":478},[438,1974,570],{"class":448},[438,1976,1670],{"class":455},[438,1978,1979],{"class":448},", { system: ",[438,1981,1982],{"class":455},"`${",[438,1984,574],{"class":448},[438,1986,1987],{"class":455},"} 加入了聊天室`",[438,1989,1037],{"class":448},[438,1991,1992,1994,1996,1999,2002],{"class":440,"line":510},[438,1993,641],{"class":448},[438,1995,644],{"class":478},[438,1997,1998],{"class":448},"({ system: ",[438,2000,2001],{"class":455},"\"欢迎来到聊天室！\"",[438,2003,1037],{"class":448},[438,2005,2006],{"class":440,"line":617},[438,2007,507],{"class":448},[438,2009,2010,2012,2014,2016,2018,2020],{"class":440,"line":638},[438,2011,602],{"class":478},[438,2013,570],{"class":448},[438,2015,574],{"class":573},[438,2017,609],{"class":448},[438,2019,612],{"class":573},[438,2021,577],{"class":448},[438,2023,2024],{"class":440,"line":655},[438,2025,2026],{"class":1102},"    \u002F\u002F 广播给其他所有订阅者\n",[438,2028,2029,2031,2033,2035,2037],{"class":440,"line":660},[438,2030,641],{"class":448},[438,2032,1665],{"class":478},[438,2034,570],{"class":448},[438,2036,1670],{"class":455},[438,2038,2039],{"class":448},", {\n",[438,2041,2042,2045,2048],{"class":440,"line":677},[438,2043,2044],{"class":448},"      user: peer.",[438,2046,2047],{"class":478},"toString",[438,2049,2050],{"class":448},"(),\n",[438,2052,2053,2056,2058],{"class":440,"line":692},[438,2054,2055],{"class":448},"      text: message.",[438,2057,632],{"class":478},[438,2059,2050],{"class":448},[438,2061,2062],{"class":440,"line":697},[438,2063,2064],{"class":448},"    });\n",[438,2066,2067],{"class":440,"line":714},[438,2068,2069],{"class":1102},"    \u002F\u002F 回显给发送者\n",[438,2071,2072,2074,2076,2079,2082,2085,2087],{"class":440,"line":729},[438,2073,641],{"class":448},[438,2075,644],{"class":478},[438,2077,2078],{"class":448},"({ user: ",[438,2080,2081],{"class":455},"\"你\"",[438,2083,2084],{"class":448},", text: message.",[438,2086,632],{"class":478},[438,2088,2089],{"class":448},"() });\n",[438,2091,2092],{"class":440,"line":734},[438,2093,507],{"class":448},[438,2095,2096,2098,2100,2102],{"class":440,"line":1106},[438,2097,663],{"class":478},[438,2099,570],{"class":448},[438,2101,574],{"class":573},[438,2103,577],{"class":448},[438,2105,2107,2109,2111,2113,2115,2117,2119,2121,2124],{"class":440,"line":2106},19,[438,2108,641],{"class":448},[438,2110,1665],{"class":478},[438,2112,570],{"class":448},[438,2114,1670],{"class":455},[438,2116,1979],{"class":448},[438,2118,1982],{"class":455},[438,2120,574],{"class":448},[438,2122,2123],{"class":455},"} 离开了聊天室`",[438,2125,1037],{"class":448},[438,2127,2129],{"class":440,"line":2128},20,[438,2130,507],{"class":448},[438,2132,2134],{"class":440,"line":2133},21,[438,2135,513],{"class":448},[2137,2138,2139],"note",{},[408,2140,2141,2144,2145,2148,2149,1306],{},[435,2142,2143],{},"peer.publish()"," 会将消息发送给该主题的所有订阅者，但",[1650,2146,2147],{},"不包括","发送消息的 peer 自己。如果也要发给发布者，请使用 ",[435,2150,2151],{},"peer.send()",[752,2153,2154],{"id":2154},"命名空间",[408,2156,2157,2158,2160],{},"命名空间为 WebSocket 连接提供隔离的发布\u002F订阅分组。每个 peer 都属于某一个命名空间，而 ",[435,2159,2143],{}," 只会向同一命名空间内的 peer 广播。",[408,2162,2163,2164,2168],{},"默认情况下，命名空间由请求 URL 的路径名推导而来。这与",[525,2165,2167],{"href":2166},"\u002Fdocs\u002Frouting#dynamic-routes","动态路由","能够自然配合，也就是说每个路径都会拥有自己独立的命名空间：",[428,2170,2173],{"className":430,"code":2171,"filename":2172,"language":433,"meta":5,"style":5},"import { defineWebSocketHandler } from \"nitro\";\n\nexport default defineWebSocketHandler({\n  open(peer) {\n    peer.subscribe(\"messages\");\n    peer.publish(\"messages\", `${peer} 加入了 ${peer.namespace}`);\n  },\n  message(peer, message) {\n    \u002F\u002F 只会发送给同一房间内的 peer\n    peer.publish(\"messages\", `${peer}: ${message.text()}`);\n  },\n  close(peer) {\n    peer.publish(\"messages\", `${peer} 离开了`);\n  },\n});\n","routes\u002Frooms\u002F[room].ts",[435,2174,2175,2187,2191,2201,2211,2224,2253,2257,2271,2276,2308,2312,2322,2343,2347],{"__ignoreMap":5},[438,2176,2177,2179,2181,2183,2185],{"class":440,"line":441},[438,2178,445],{"class":444},[438,2180,541],{"class":448},[438,2182,452],{"class":444},[438,2184,456],{"class":455},[438,2186,459],{"class":448},[438,2188,2189],{"class":440,"line":462},[438,2190,466],{"emptyLinePlaceholder":465},[438,2192,2193,2195,2197,2199],{"class":440,"line":469},[438,2194,472],{"class":444},[438,2196,475],{"class":444},[438,2198,560],{"class":478},[438,2200,482],{"class":448},[438,2202,2203,2205,2207,2209],{"class":440,"line":485},[438,2204,567],{"class":478},[438,2206,570],{"class":448},[438,2208,574],{"class":573},[438,2210,577],{"class":448},[438,2212,2213,2215,2217,2219,2222],{"class":440,"line":491},[438,2214,641],{"class":448},[438,2216,1605],{"class":478},[438,2218,570],{"class":448},[438,2220,2221],{"class":455},"\"messages\"",[438,2223,652],{"class":448},[438,2225,2226,2228,2230,2232,2234,2236,2238,2240,2243,2245,2247,2249,2251],{"class":440,"line":504},[438,2227,641],{"class":448},[438,2229,1665],{"class":478},[438,2231,570],{"class":448},[438,2233,2221],{"class":455},[438,2235,609],{"class":448},[438,2237,1982],{"class":455},[438,2239,574],{"class":448},[438,2241,2242],{"class":455},"} 加入了 ${",[438,2244,574],{"class":448},[438,2246,1334],{"class":455},[438,2248,1158],{"class":448},[438,2250,1348],{"class":455},[438,2252,652],{"class":448},[438,2254,2255],{"class":440,"line":510},[438,2256,507],{"class":448},[438,2258,2259,2261,2263,2265,2267,2269],{"class":440,"line":617},[438,2260,602],{"class":478},[438,2262,570],{"class":448},[438,2264,574],{"class":573},[438,2266,609],{"class":448},[438,2268,612],{"class":573},[438,2270,577],{"class":448},[438,2272,2273],{"class":440,"line":638},[438,2274,2275],{"class":1102},"    \u002F\u002F 只会发送给同一房间内的 peer\n",[438,2277,2278,2280,2282,2284,2286,2288,2290,2292,2295,2297,2299,2301,2304,2306],{"class":440,"line":655},[438,2279,641],{"class":448},[438,2281,1665],{"class":478},[438,2283,570],{"class":448},[438,2285,2221],{"class":455},[438,2287,609],{"class":448},[438,2289,1982],{"class":455},[438,2291,574],{"class":448},[438,2293,2294],{"class":455},"}: ${",[438,2296,612],{"class":448},[438,2298,1334],{"class":455},[438,2300,632],{"class":478},[438,2302,2303],{"class":455},"()",[438,2305,1348],{"class":455},[438,2307,652],{"class":448},[438,2309,2310],{"class":440,"line":660},[438,2311,507],{"class":448},[438,2313,2314,2316,2318,2320],{"class":440,"line":677},[438,2315,663],{"class":478},[438,2317,570],{"class":448},[438,2319,574],{"class":573},[438,2321,577],{"class":448},[438,2323,2324,2326,2328,2330,2332,2334,2336,2338,2341],{"class":440,"line":692},[438,2325,641],{"class":448},[438,2327,1665],{"class":478},[438,2329,570],{"class":448},[438,2331,2221],{"class":455},[438,2333,609],{"class":448},[438,2335,1982],{"class":455},[438,2337,574],{"class":448},[438,2339,2340],{"class":455},"} 离开了`",[438,2342,652],{"class":448},[438,2344,2345],{"class":440,"line":697},[438,2346,507],{"class":448},[438,2348,2349],{"class":440,"line":714},[438,2350,513],{"class":448},[408,2352,2353,2354,2357,2358,2361],{},"在这个示例中，连接到 ",[435,2355,2356],{},"\u002Frooms\u002Fgame"," 的客户端会与连接到 ",[435,2359,2360],{},"\u002Frooms\u002Flobby"," 的客户端彼此隔离，因为每个路径都对应自己的命名空间。",[408,2363,2364,2365,2367,2368,2370],{},"如果要覆盖默认命名空间，可以在 ",[435,2366,908],{}," 钩子中返回自定义的 ",[435,2369,1158],{},"：",[428,2372,2374],{"className":430,"code":2373,"filename":745,"language":433,"meta":5,"style":5},"import { defineWebSocketHandler } from \"nitro\";\n\nexport default defineWebSocketHandler({\n  upgrade(request) {\n    \u002F\u002F 按查询参数分组连接，而不是按路径名\n    const url = new URL(request.url);\n    const channel = url.searchParams.get(\"channel\") || \"general\";\n    return {\n      namespace: `chat:${channel}`,\n    };\n  },\n  open(peer) {\n    peer.subscribe(\"messages\");\n    peer.publish(\"messages\", `${peer} 加入了`);\n  },\n  message(peer, message) {\n    peer.publish(\"messages\", `${peer}: ${message.text()}`);\n  },\n  close(peer) {\n    peer.publish(\"messages\", `${peer} 离开了`);\n  },\n});\n",[435,2375,2376,2388,2392,2402,2412,2417,2431,2459,2465,2480,2484,2488,2498,2510,2531,2535,2549,2579,2583,2593,2613,2617],{"__ignoreMap":5},[438,2377,2378,2380,2382,2384,2386],{"class":440,"line":441},[438,2379,445],{"class":444},[438,2381,541],{"class":448},[438,2383,452],{"class":444},[438,2385,456],{"class":455},[438,2387,459],{"class":448},[438,2389,2390],{"class":440,"line":462},[438,2391,466],{"emptyLinePlaceholder":465},[438,2393,2394,2396,2398,2400],{"class":440,"line":469},[438,2395,472],{"class":444},[438,2397,475],{"class":444},[438,2399,560],{"class":478},[438,2401,482],{"class":448},[438,2403,2404,2406,2408,2410],{"class":440,"line":485},[438,2405,949],{"class":478},[438,2407,570],{"class":448},[438,2409,954],{"class":573},[438,2411,577],{"class":448},[438,2413,2414],{"class":440,"line":491},[438,2415,2416],{"class":1102},"    \u002F\u002F 按查询参数分组连接，而不是按路径名\n",[438,2418,2419,2421,2423,2425,2427,2429],{"class":440,"line":504},[438,2420,961],{"class":444},[438,2422,964],{"class":497},[438,2424,782],{"class":444},[438,2426,785],{"class":444},[438,2428,971],{"class":478},[438,2430,974],{"class":448},[438,2432,2433,2435,2438,2440,2442,2444,2446,2449,2451,2454,2457],{"class":440,"line":510},[438,2434,961],{"class":444},[438,2436,2437],{"class":497}," channel",[438,2439,782],{"class":444},[438,2441,986],{"class":448},[438,2443,989],{"class":478},[438,2445,570],{"class":448},[438,2447,2448],{"class":455},"\"channel\"",[438,2450,877],{"class":448},[438,2452,2453],{"class":444},"||",[438,2455,2456],{"class":455}," \"general\"",[438,2458,459],{"class":448},[438,2460,2461,2463],{"class":440,"line":617},[438,2462,1047],{"class":444},[438,2464,821],{"class":448},[438,2466,2467,2470,2473,2476,2478],{"class":440,"line":638},[438,2468,2469],{"class":448},"      namespace: ",[438,2471,2472],{"class":455},"`chat:${",[438,2474,2475],{"class":448},"channel",[438,2477,1348],{"class":455},[438,2479,501],{"class":448},[438,2481,2482],{"class":440,"line":655},[438,2483,1065],{"class":448},[438,2485,2486],{"class":440,"line":660},[438,2487,507],{"class":448},[438,2489,2490,2492,2494,2496],{"class":440,"line":677},[438,2491,567],{"class":478},[438,2493,570],{"class":448},[438,2495,574],{"class":573},[438,2497,577],{"class":448},[438,2499,2500,2502,2504,2506,2508],{"class":440,"line":692},[438,2501,641],{"class":448},[438,2503,1605],{"class":478},[438,2505,570],{"class":448},[438,2507,2221],{"class":455},[438,2509,652],{"class":448},[438,2511,2512,2514,2516,2518,2520,2522,2524,2526,2529],{"class":440,"line":697},[438,2513,641],{"class":448},[438,2515,1665],{"class":478},[438,2517,570],{"class":448},[438,2519,2221],{"class":455},[438,2521,609],{"class":448},[438,2523,1982],{"class":455},[438,2525,574],{"class":448},[438,2527,2528],{"class":455},"} 加入了`",[438,2530,652],{"class":448},[438,2532,2533],{"class":440,"line":714},[438,2534,507],{"class":448},[438,2536,2537,2539,2541,2543,2545,2547],{"class":440,"line":729},[438,2538,602],{"class":478},[438,2540,570],{"class":448},[438,2542,574],{"class":573},[438,2544,609],{"class":448},[438,2546,612],{"class":573},[438,2548,577],{"class":448},[438,2550,2551,2553,2555,2557,2559,2561,2563,2565,2567,2569,2571,2573,2575,2577],{"class":440,"line":734},[438,2552,641],{"class":448},[438,2554,1665],{"class":478},[438,2556,570],{"class":448},[438,2558,2221],{"class":455},[438,2560,609],{"class":448},[438,2562,1982],{"class":455},[438,2564,574],{"class":448},[438,2566,2294],{"class":455},[438,2568,612],{"class":448},[438,2570,1334],{"class":455},[438,2572,632],{"class":478},[438,2574,2303],{"class":455},[438,2576,1348],{"class":455},[438,2578,652],{"class":448},[438,2580,2581],{"class":440,"line":1106},[438,2582,507],{"class":448},[438,2584,2585,2587,2589,2591],{"class":440,"line":2106},[438,2586,663],{"class":478},[438,2588,570],{"class":448},[438,2590,574],{"class":573},[438,2592,577],{"class":448},[438,2594,2595,2597,2599,2601,2603,2605,2607,2609,2611],{"class":440,"line":2128},[438,2596,641],{"class":448},[438,2598,1665],{"class":478},[438,2600,570],{"class":448},[438,2602,2221],{"class":455},[438,2604,609],{"class":448},[438,2606,1982],{"class":455},[438,2608,574],{"class":448},[438,2610,2340],{"class":455},[438,2612,652],{"class":448},[438,2614,2615],{"class":440,"line":2133},[438,2616,507],{"class":448},[438,2618,2620],{"class":440,"line":2619},22,[438,2621,513],{"class":448},[417,2623,2625],{"id":2624},"server-sent-eventssse","Server-Sent Events（SSE）",[408,2627,2628,2633],{},[525,2629,2632],{"href":2630,"rel":2631},"https:\u002F\u002Fdeveloper.mozilla.org\u002Fen-US\u002Fdocs\u002FWeb\u002FAPI\u002FServer-sent_events",[762],"Server-Sent Events"," 在只需要服务端到客户端单向流式推送时，是一种更简单的替代方案。与 WebSocket 不同，SSE 使用标准 HTTP，并支持自动重连。",[428,2635,2638],{"className":430,"code":2636,"filename":2637,"language":433,"meta":5,"style":5},"import { defineHandler } from \"nitro\";\nimport { createEventStream } from \"nitro\u002Fh3\";\n\nexport default defineHandler((event) => {\n  const stream = createEventStream(event);\n\n  const interval = setInterval(async () => {\n    await stream.push(`Message @ ${new Date().toLocaleTimeString()}`);\n  }, 1000);\n\n  stream.onClosed(() => {\n    clearInterval(interval);\n  });\n\n  return stream.send();\n});\n","routes\u002Fsse.ts",[435,2639,2640,2653,2667,2671,2691,2706,2710,2734,2768,2777,2781,2796,2804,2809,2813,2824],{"__ignoreMap":5},[438,2641,2642,2644,2647,2649,2651],{"class":440,"line":441},[438,2643,445],{"class":444},[438,2645,2646],{"class":448}," { defineHandler } ",[438,2648,452],{"class":444},[438,2650,456],{"class":455},[438,2652,459],{"class":448},[438,2654,2655,2657,2660,2662,2665],{"class":440,"line":462},[438,2656,445],{"class":444},[438,2658,2659],{"class":448}," { createEventStream } ",[438,2661,452],{"class":444},[438,2663,2664],{"class":455}," \"nitro\u002Fh3\"",[438,2666,459],{"class":448},[438,2668,2669],{"class":440,"line":469},[438,2670,466],{"emptyLinePlaceholder":465},[438,2672,2673,2675,2677,2680,2683,2685,2687,2689],{"class":440,"line":485},[438,2674,472],{"class":444},[438,2676,475],{"class":444},[438,2678,2679],{"class":478}," defineHandler",[438,2681,2682],{"class":448},"((",[438,2684,874],{"class":573},[438,2686,877],{"class":448},[438,2688,818],{"class":444},[438,2690,821],{"class":448},[438,2692,2693,2695,2698,2700,2703],{"class":440,"line":491},[438,2694,1255],{"class":444},[438,2696,2697],{"class":497}," stream",[438,2699,782],{"class":444},[438,2701,2702],{"class":478}," createEventStream",[438,2704,2705],{"class":448},"(event);\n",[438,2707,2708],{"class":440,"line":504},[438,2709,466],{"emptyLinePlaceholder":465},[438,2711,2712,2714,2717,2719,2722,2724,2727,2730,2732],{"class":440,"line":510},[438,2713,1255],{"class":444},[438,2715,2716],{"class":497}," interval",[438,2718,782],{"class":444},[438,2720,2721],{"class":478}," setInterval",[438,2723,570],{"class":448},[438,2725,2726],{"class":444},"async",[438,2728,2729],{"class":448}," () ",[438,2731,818],{"class":444},[438,2733,821],{"class":448},[438,2735,2736,2739,2742,2745,2747,2750,2753,2756,2759,2762,2764,2766],{"class":440,"line":617},[438,2737,2738],{"class":444},"    await",[438,2740,2741],{"class":448}," stream.",[438,2743,2744],{"class":478},"push",[438,2746,570],{"class":448},[438,2748,2749],{"class":455},"`Message @ ${",[438,2751,2752],{"class":444},"new",[438,2754,2755],{"class":478}," Date",[438,2757,2758],{"class":455},"().",[438,2760,2761],{"class":478},"toLocaleTimeString",[438,2763,2303],{"class":455},[438,2765,1348],{"class":455},[438,2767,652],{"class":448},[438,2769,2770,2773,2775],{"class":440,"line":638},[438,2771,2772],{"class":448},"  }, ",[438,2774,1708],{"class":497},[438,2776,652],{"class":448},[438,2778,2779],{"class":440,"line":655},[438,2780,466],{"emptyLinePlaceholder":465},[438,2782,2783,2786,2789,2792,2794],{"class":440,"line":660},[438,2784,2785],{"class":448},"  stream.",[438,2787,2788],{"class":478},"onClosed",[438,2790,2791],{"class":448},"(() ",[438,2793,818],{"class":444},[438,2795,821],{"class":448},[438,2797,2798,2801],{"class":440,"line":677},[438,2799,2800],{"class":478},"    clearInterval",[438,2802,2803],{"class":448},"(interval);\n",[438,2805,2806],{"class":440,"line":692},[438,2807,2808],{"class":448},"  });\n",[438,2810,2811],{"class":440,"line":697},[438,2812,466],{"emptyLinePlaceholder":465},[438,2814,2815,2818,2820,2822],{"class":440,"line":714},[438,2816,2817],{"class":444},"  return",[438,2819,2741],{"class":448},[438,2821,644],{"class":478},[438,2823,1268],{"class":448},[438,2825,2826],{"class":440,"line":729},[438,2827,513],{"class":448},[408,2829,2830,2831,2836],{},"客户端可以通过 ",[525,2832,2835],{"href":2833,"rel":2834},"https:\u002F\u002Fdeveloper.mozilla.org\u002Fen-US\u002Fdocs\u002FWeb\u002FAPI\u002FEventSource",[762],"EventSource API"," 连接：",[428,2838,2840],{"className":767,"code":2839,"language":769,"meta":5,"style":5},"const source = new EventSource(\"\u002Fsse\");\n\nsource.onmessage = (event) => {\n  console.log(event.data);\n};\n",[435,2841,2842,2863,2867,2887,2896],{"__ignoreMap":5},[438,2843,2844,2846,2849,2851,2853,2856,2858,2861],{"class":440,"line":441},[438,2845,776],{"class":444},[438,2847,2848],{"class":497}," source",[438,2850,782],{"class":444},[438,2852,785],{"class":444},[438,2854,2855],{"class":478}," EventSource",[438,2857,570],{"class":448},[438,2859,2860],{"class":455},"\"\u002Fsse\"",[438,2862,652],{"class":448},[438,2864,2865],{"class":440,"line":462},[438,2866,466],{"emptyLinePlaceholder":465},[438,2868,2869,2872,2875,2877,2879,2881,2883,2885],{"class":440,"line":469},[438,2870,2871],{"class":448},"source.",[438,2873,2874],{"class":478},"onmessage",[438,2876,782],{"class":444},[438,2878,1004],{"class":448},[438,2880,874],{"class":573},[438,2882,877],{"class":448},[438,2884,818],{"class":444},[438,2886,821],{"class":448},[438,2888,2889,2891,2893],{"class":440,"line":485},[438,2890,826],{"class":448},[438,2892,585],{"class":478},[438,2894,2895],{"class":448},"(event.data);\n",[438,2897,2898],{"class":440,"line":491},[438,2899,2900],{"class":448},"};\n",[752,2902,2903],{"id":2903},"结构化消息",[408,2905,2906,2907,2909,2910,1302,2912,2915],{},"SSE 消息支持可选的 ",[435,2908,1424],{},"、",[435,2911,874],{},[435,2913,2914],{},"retry"," 字段：",[428,2917,2920],{"className":430,"code":2918,"filename":2919,"language":433,"meta":5,"style":5},"import { defineHandler } from \"nitro\";\nimport { createEventStream } from \"nitro\u002Fh3\";\n\nexport default defineHandler((event) => {\n  const stream = createEventStream(event);\n  let id = 0;\n\n  const interval = setInterval(async () => {\n    await stream.push({\n      id: String(id++),\n      event: \"update\",\n      data: JSON.stringify({ value: Math.random() }),\n      retry: 3000,\n    });\n  }, 1000);\n\n  stream.onClosed(() => {\n    clearInterval(interval);\n  });\n\n  return stream.send();\n});\n","routes\u002Fevents.ts",[435,2921,2922,2934,2946,2950,2968,2980,2996,3000,3020,3030,3047,3057,3079,3089,3093,3101,3105,3117,3123,3127,3131,3141],{"__ignoreMap":5},[438,2923,2924,2926,2928,2930,2932],{"class":440,"line":441},[438,2925,445],{"class":444},[438,2927,2646],{"class":448},[438,2929,452],{"class":444},[438,2931,456],{"class":455},[438,2933,459],{"class":448},[438,2935,2936,2938,2940,2942,2944],{"class":440,"line":462},[438,2937,445],{"class":444},[438,2939,2659],{"class":448},[438,2941,452],{"class":444},[438,2943,2664],{"class":455},[438,2945,459],{"class":448},[438,2947,2948],{"class":440,"line":469},[438,2949,466],{"emptyLinePlaceholder":465},[438,2951,2952,2954,2956,2958,2960,2962,2964,2966],{"class":440,"line":485},[438,2953,472],{"class":444},[438,2955,475],{"class":444},[438,2957,2679],{"class":478},[438,2959,2682],{"class":448},[438,2961,874],{"class":573},[438,2963,877],{"class":448},[438,2965,818],{"class":444},[438,2967,821],{"class":448},[438,2969,2970,2972,2974,2976,2978],{"class":440,"line":491},[438,2971,1255],{"class":444},[438,2973,2697],{"class":497},[438,2975,782],{"class":444},[438,2977,2702],{"class":478},[438,2979,2705],{"class":448},[438,2981,2982,2985,2988,2991,2994],{"class":440,"line":504},[438,2983,2984],{"class":444},"  let",[438,2986,2987],{"class":448}," id ",[438,2989,2990],{"class":444},"=",[438,2992,2993],{"class":497}," 0",[438,2995,459],{"class":448},[438,2997,2998],{"class":440,"line":510},[438,2999,466],{"emptyLinePlaceholder":465},[438,3001,3002,3004,3006,3008,3010,3012,3014,3016,3018],{"class":440,"line":617},[438,3003,1255],{"class":444},[438,3005,2716],{"class":497},[438,3007,782],{"class":444},[438,3009,2721],{"class":478},[438,3011,570],{"class":448},[438,3013,2726],{"class":444},[438,3015,2729],{"class":448},[438,3017,818],{"class":444},[438,3019,821],{"class":448},[438,3021,3022,3024,3026,3028],{"class":440,"line":638},[438,3023,2738],{"class":444},[438,3025,2741],{"class":448},[438,3027,2744],{"class":478},[438,3029,482],{"class":448},[438,3031,3032,3035,3038,3041,3044],{"class":440,"line":655},[438,3033,3034],{"class":448},"      id: ",[438,3036,3037],{"class":478},"String",[438,3039,3040],{"class":448},"(id",[438,3042,3043],{"class":444},"++",[438,3045,3046],{"class":448},"),\n",[438,3048,3049,3052,3055],{"class":440,"line":660},[438,3050,3051],{"class":448},"      event: ",[438,3053,3054],{"class":455},"\"update\"",[438,3056,501],{"class":448},[438,3058,3059,3062,3065,3067,3070,3073,3076],{"class":440,"line":677},[438,3060,3061],{"class":448},"      data: ",[438,3063,3064],{"class":497},"JSON",[438,3066,1334],{"class":448},[438,3068,3069],{"class":478},"stringify",[438,3071,3072],{"class":448},"({ value: Math.",[438,3074,3075],{"class":478},"random",[438,3077,3078],{"class":448},"() }),\n",[438,3080,3081,3084,3087],{"class":440,"line":692},[438,3082,3083],{"class":448},"      retry: ",[438,3085,3086],{"class":497},"3000",[438,3088,501],{"class":448},[438,3090,3091],{"class":440,"line":697},[438,3092,2064],{"class":448},[438,3094,3095,3097,3099],{"class":440,"line":714},[438,3096,2772],{"class":448},[438,3098,1708],{"class":497},[438,3100,652],{"class":448},[438,3102,3103],{"class":440,"line":729},[438,3104,466],{"emptyLinePlaceholder":465},[438,3106,3107,3109,3111,3113,3115],{"class":440,"line":734},[438,3108,2785],{"class":448},[438,3110,2788],{"class":478},[438,3112,2791],{"class":448},[438,3114,818],{"class":444},[438,3116,821],{"class":448},[438,3118,3119,3121],{"class":440,"line":1106},[438,3120,2800],{"class":478},[438,3122,2803],{"class":448},[438,3124,3125],{"class":440,"line":2106},[438,3126,2808],{"class":448},[438,3128,3129],{"class":440,"line":2128},[438,3130,466],{"emptyLinePlaceholder":465},[438,3132,3133,3135,3137,3139],{"class":440,"line":2133},[438,3134,2817],{"class":444},[438,3136,2741],{"class":448},[438,3138,644],{"class":478},[438,3140,1268],{"class":448},[438,3142,3143],{"class":440,"line":2619},[438,3144,513],{"class":448},[412,3146],{"title":3147,"to":3148},"H3 Documentation","https:\u002F\u002Fh3.dev\u002F",[3150,3151,3152],"style",{},"html pre.shiki code .so5gQ, html code.shiki .so5gQ{--shiki-light:#D73A49;--shiki-default:#F97583;--shiki-dark:#F97583}html pre.shiki code .slsVL, html code.shiki .slsVL{--shiki-light:#24292E;--shiki-default:#E1E4E8;--shiki-dark:#E1E4E8}html pre.shiki code .sfrk1, html code.shiki .sfrk1{--shiki-light:#032F62;--shiki-default:#9ECBFF;--shiki-dark:#9ECBFF}html pre.shiki code .shcOC, html code.shiki .shcOC{--shiki-light:#6F42C1;--shiki-default:#B392F0;--shiki-dark:#B392F0}html pre.shiki code .suiK_, html code.shiki .suiK_{--shiki-light:#005CC5;--shiki-default:#79B8FF;--shiki-dark:#79B8FF}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sQHwn, html code.shiki .sQHwn{--shiki-light:#E36209;--shiki-default:#FFAB70;--shiki-dark:#FFAB70}html pre.shiki code .sCsY4, html code.shiki .sCsY4{--shiki-light:#6A737D;--shiki-default:#6A737D;--shiki-dark:#6A737D}",{"title":5,"searchDepth":462,"depth":462,"links":3154},[3155,3156,3159,3166,3170,3171,3174],{"id":419,"depth":462,"text":420},{"id":516,"depth":462,"text":516,"children":3157},[3158],{"id":754,"depth":469,"text":754},{"id":902,"depth":462,"text":902,"children":3160},[3161,3162,3163,3164,3165],{"id":908,"depth":469,"text":908},{"id":1195,"depth":469,"text":1195},{"id":612,"depth":469,"text":612},{"id":1291,"depth":469,"text":1291},{"id":709,"depth":469,"text":709},{"id":574,"depth":462,"text":1393,"children":3167},[3168,3169],{"id":1126,"depth":469,"text":1126},{"id":1536,"depth":469,"text":1536},{"id":1727,"depth":462,"text":1728},{"id":1909,"depth":462,"text":1910,"children":3172},[3173],{"id":2154,"depth":469,"text":2154},{"id":2624,"depth":462,"text":2625,"children":3175},[3176],{"id":2903,"depth":469,"text":2903},"Nitro 基于 CrossWS 和 H3 提供跨平台的 WebSocket 支持。","md",{"icon":66},{"icon":66},{"title":63,"description":3177},"pthj_L77iWR2SDbdmrcolb4AQKV-WnsGbysX68LPOG4",[3184,3186],{"title":58,"path":59,"stem":60,"description":3185,"icon":61,"children":-1},"Nitro 任务允许在运行时执行一次性操作。",{"title":68,"path":69,"stem":70,"description":3187,"icon":71,"children":-1},"使用服务端入口创建一个全局中间件，该中间件会在所有路由匹配之前运行。",1777215897052]