【发布时间】:2020-06-25 16:04:10
【问题描述】:
我想创建一个与 websocket 建立连接的组件。
我有一个当前创建 websocket 连接的 go 后端。
r.LoadHTMLFiles("index.html")
r.GET("/room/:roomId", func(c *gin.Context) {
c.HTML(200, "index.html", nil)
})
r.GET("/ws/:roomId", func(c *gin.Context) {
roomID := c.Param("roomId")
handler.OpenWebSocket(c.Writer, c.Request, roomID)
})
这是我的html文件
<!DOCTYPE html>
<html lang="en">
<head>
<title>Chat Example</title>
<script type="text/javascript">
window.onload = function () {
let conn;
let msg = document.getElementById("msg");
let log = document.getElementById("log");
function appendLog(item) {
let doScroll = log.scrollTop > log.scrollHeight - log.clientHeight - 1;
log.appendChild(item);
if (doScroll) {
log.scrollTop = log.scrollHeight - log.clientHeight;
}
}
document.getElementById("form").onsubmit = function () {
if (!conn) {
console.log("hello1")
return false;
}
if (!msg.value) {
console.log("hello2")
return false;
}
conn.send(msg.value);
msg.value = "";
return false;
};
if (window["WebSocket"]) {
const params = window.location.href.split("/");
const roomId = params[params.length - 1];
const url ="ws://" + document.location.host + "/ws/" + 99
conn = new WebSocket(url);
console.log(url)
conn.onclose = function (evt) {
console.log("i was closed")
let item = document.createElement("div");
item.innerHTML = "<b>Connection closed.</b>";
appendLog(item);
};
conn.onmessage = function (evt) {
let messages = evt.data.split('\n');
console.log(messages)
for (let i = 0; i < messages.length; i++) {
let item = document.createElement("div");
item.innerText = messages[i];
appendLog(item);
}
};
} else {
let item = document.createElement("div");
item.innerHTML = "<b>Your browser does not support WebSockets.</b>";
appendLog(item);
}
};
</script>
<style type="text/css">
body {
overflow: hidden;
padding: 0;
margin: 0;
width: 100%;
height: 100%;
background: gray;
}
#log {
background: white;
margin: 0;
padding: 0.5em 0.5em 0.5em 0.5em;
position: absolute;
top: 0.5em;
left: 0.5em;
right: 0.5em;
bottom: 3em;
overflow: auto;
}
#form {
padding: 0 0.5em 0 0.5em;
margin: 0;
position: absolute;
bottom: 1em;
left: 0px;
width: 100%;
overflow: hidden;
}
</style>
</head>
<body>
<div id="log"></div>
<form id="form">
<input type="text" id="msg" size="64" autofocus/>
<input type="submit" value="Send"/>
</form>
</body>
</html>
这很好,如果我访问 http://localhost:8080/room/12 然后我可以访问聊天,一切都很好。但是,当我尝试使用 react 和 nextjs 建立连接时,我得到了
WebSocket connection to 'ws://localhost:8080/ws' failed: Error during WebSocket handshake: Unexpected response code: 404
这是我的反应页面。
import React, {useState, useEffect, useRef } from 'react'
import Head from 'next/head'
import { useRouter } from 'next/router'
import { initializeApollo, useApollo } from '@/utils/apollo'
import { ProfileDataQuery } from '@/gql'
import { UserData } from '@/types'
import { NextPageContext } from 'next'
type ProfilePageProps = {
initialApolloState: any
}
const ProfilePage: React.FunctionComponent<ProfilePageProps> = ({ initialApolloState }) => {
const apolloClient = useApollo(initialApolloState)
const router = useRouter()
const [isPaused, setPause] = useState(false)
useEffect(() => {
ws.current = new WebSocket("ws://localhost:8080/ws");
ws.current.onopen = () => console.log("ws opened");
ws.current.onclose = () => console.log("ws closed");
return () => {
ws.current.close()
}
}, []);
useEffect(() => {
if (!ws.current) return;
ws.current.onmessage = e => {
if (isPaused) return;
const message = JSON.parse(e.data);
console.log("e", message);
};
}, [isPaused]);
const data = apolloClient.readQuery({
query: ProfileDataQuery,
variables: {
uuid: router.query.uuid
}
})
console.log(data)
const userData: UserData = data.Users[0]
const followers: UserData[] = data.followers
const following: UserData[] = data.following
const ws = useRef(null)
return (
<div className="main flex flex-col">
<Head>
<title>{ userData.username } - Omiran</title>
</Head>
<div className="flex-grow"/>
<div className="flex flex-col border border-gray-500 rounded-lg w-11/12 md:w-4/5 p-5 mx-auto">
<div className="flex flex-row items-center w-full">
<img
className="rounded-full mr-6"
src={userData.profilePicture}
alt={userData.username}
height={100}
width={100}
/>
<div className="flex flex-col">
<h1 className="text-xl sm:text-2xl md:text-3xl text-left">{userData.username}</h1>
<div className="flex flex-row">
<span className="text-sm mr-3">
<b>{followers.length}</b> Followers
</span>
<span className="text-sm">
<b>{following.length}</b> Following
</span>
</div>
</div>
<div className="flex-grow" />
<button className="btn btn-orange">{true ? 'Edit Profile' : 'Follow'}</button>
</div>
</div>
<div className="flex-grow-3"/>
</div>
)
}
export async function getServerSideProps(context: NextPageContext) {
const { uuid } = context.query
const apolloClient = initializeApollo()
await apolloClient
.query({
query: ProfileDataQuery,
variables: {
uuid: String(uuid)
}
})
return {
props: {
initialApolloState: apolloClient.cache.extract(),
},
}
}
export default ProfilePage
【问题讨论】: