WebTransportの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が追加で定義されないと色々混乱しそう。