* Sends a bidi request * @param params * @returns {Promise }
(params)
| 249 | * @returns {Promise<unknown>} |
| 250 | */ |
| 251 | async send(params) { |
| 252 | if (this._closed) { |
| 253 | throw new Error('BiDi connection is closed') |
| 254 | } |
| 255 | if (!this.connected) { |
| 256 | await this.waitForConnection() |
| 257 | } |
| 258 | // Defense in depth: even after waitForConnection() resolves, the socket |
| 259 | // may have transitioned to CLOSING/CLOSED (e.g. caller closed the raw |
| 260 | // socket). Refuse rather than throwing from inside ws.send(). |
| 261 | if (this._ws.readyState !== WebSocket.OPEN) { |
| 262 | throw new Error('BiDi connection is not open') |
| 263 | } |
| 264 | |
| 265 | const id = ++this.id |
| 266 | |
| 267 | this._ws.send(JSON.stringify({ id, ...params })) |
| 268 | |
| 269 | return new Promise((resolve, reject) => { |
| 270 | const timeoutId = setTimeout(() => { |
| 271 | this._pending.delete(id) |
| 272 | reject(new Error(`Request with id ${id} timed out`)) |
| 273 | }, RESPONSE_TIMEOUT) |
| 274 | |
| 275 | this._pending.set(id, { resolve, reject, timeoutId }) |
| 276 | }) |
| 277 | } |
| 278 | |
| 279 | /** |
| 280 | * Subscribe to events. |
no test coverage detected