Skip to content

Instantly share code, notes, and snippets.

@Kanasansoft
Created April 9, 2023 11:19
Show Gist options
  • Save Kanasansoft/f2a202c662c04f4cd007d8a962e1b038 to your computer and use it in GitHub Desktop.
Save Kanasansoft/f2a202c662c04f4cd007d8a962e1b038 to your computer and use it in GitHub Desktop.

await WebTransport.ready のようなことができる WebSocket を作ってみる

WebTransportのMDNを見ていたらこんな例を見つけた。

WebTransport - Web APIs | MDN

const transport = new WebTransport(url);
await transport.ready;

openイベントじゃなくてreadyで待つのね。 というか「await transport.ready()」ではなく「await transport.ready」なので、Promiseがそのまま入っているっぽい。

WebSocketでも同じようなことができそうなので作ってみる。

ということでまずは3秒遅れて接続を完了するWebSocketサーバを作る。

import {createServer} from 'http';
import {WebSocketServer} from 'ws';

const server = createServer();
const wss = new WebSocketServer({noServer: true});

server.on('upgrade', async function connection(request, socket, head) {
  setTimeout(() => {
    wss.handleUpgrade(request, socket, head);
  }, 3000);
});

server.listen(8080);

実際に遅延できているか確認。

const ws = new WebSocket('ws://localhost:8080');
function test(name) {
  console.log(`${name}:ready:${new Date().toISOString()}`);
  ws.addEventListener('open', () => {
    console.log(`${name}:open:${new Date().toISOString()}`);
  });
}
test('foo');
test('bar');
test('baz');

実行。

foo:ready:2023-04-09T10:36:20.609Z
bar:ready:2023-04-09T10:36:20.609Z
baz:ready:2023-04-09T10:36:20.609Z
foo:open:2023-04-09T10:36:23.621Z
bar:open:2023-04-09T10:36:23.621Z
baz:open:2023-04-09T10:36:23.621Z

はい。できました。

じゃあ、ready可能なWebSocketを作ってみる。

class ReadyableWebSocket extends WebSocket {
  ready = null;
  #resolve = null;
  constructor(...args) {
    super(...args);
    this.ready = new Promise((resolve, reject) => {
      this.#resolve = resolve;
    });
    this.addEventListener('open', () => {
      this.#resolve();
    });
  }
}

できました。 というか「ReadyableWebSocket」って英語あってる?

早速使ってみる。

const rws = new ReadyableWebSocket('ws://localhost:8080');
async function test(name) {
  console.log(`${name}:ready:${new Date().toISOString()}`);
  await rws.ready;
  console.log(`${name}:open:${new Date().toISOString()}`);
}
test('foo');
test('bar');
test('baz');

実行結果。

foo:ready:2023-04-09T10:47:15.996Z
bar:ready:2023-04-09T10:47:15.996Z
baz:ready:2023-04-09T10:47:15.996Z
foo:open:2023-04-09T10:47:19.005Z
bar:open:2023-04-09T10:47:19.005Z
baz:open:2023-04-09T10:47:19.006Z

はい。いけました。

というか、WebTransportにopenイベントが定義されるかWebSocketにreadyが追加で定義されないと色々混乱しそう。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment