0
1

「WebSocket is closed before the connection is established」が出たときの原因

Last updated at Posted at 2024-08-31

トラブル

  • webアプリケーションを作っているときに,サーバとwebsocketで通信をできるようにしたい
  • 接続しようとするとうまくできず,ブラウザの開発者ツールで次のエラーが出る
    image.png

原因の特定方法

よくある原因としては「ブラウザのページのロードが完了してない時にwebsocketの接続をしようとしている」というものである.

これが原因かどうかは次の手順を踏んで確認してください.

  1. ブラウザでF12キーなどを押して開発者ツールを開き,コンソールに次のようにコマンドを直打ちして実行してみてください
    image.png

  2. もしエラーが出ずに,次のように問題なくwebSocketのインスタンスが返ってきた場合,上記の青字の内容が原因であることがほぼ確定します
    image.png

解決策

vanillaのjavascriptで書いてる場合は,次のように

ページロード時に起動する関数をEventListenerで設定すればOK
javascriptの設定
var webSocket; // ウェブソケット
window.addEventListener('load', connect); // ページロード時にconnectを起動するように設定

// サーバとの通信を接続する関数
function connect(){
  webSocket = new WebSocket("ws://localhost:8000/");

  webSocket.onmessage = (message) => {
    console.log(message.data);
  };
}

function sendMessage(){
  // ...
}

解決策(Next.jsの場合)

どうやら開発者モードで作業する際,reactStrictModetrueにしていると,useEffectが2回呼び出されるらしい(参考).
1回目の呼び出しの際はwebsocketを一瞬繋いですぐに接続を切るためか,エラーが発生してしまう.

解決策としては次の2つが考えられる.

  • 正しい対応)「next.config.js」に書かれているreactStrictModefalseにする
  • 応急処置)下のソースコードのように,useEffectのreturn文をコメントアウトする
export default function Home() {
  const [ws, setWs] = useState(null);

  // 起動時にwebsocketを接続するuseEffect
  useEffect(() => {
    const socket = new WebSocket(url);

    socket.onmessage = (event) => {
      console.log(event.data);
    };

    // useEffectではコンポーネントのアンマウント時に起動する関数をreturnする
    // !!! ここでのトラブルを解決するために,接続解除する関数のreturnをコメントアウト !!!
    // return () => {
    //   socket.close()
    // };
  }, []);

  return <div>WebSocket Test Page</div>;
}

おわりに

  • アプリケーション作るときに毎回同じ失敗してるので覚書として残します.
  • 他の誰かも同じ問題を抱えているはず...
  • 修正前の問題があるソースコードでも環境を変えるとうまく接続できたりするので,ぶっちゃけよくわかってないところがある.
0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1