The browser's WebSocket API has send(). It does not expose a general ping() method for JavaScript to send protocol Ping frames.

If your application sends a text message such as {"type":"heartbeat"}, that is application data. The server must understand the message and define a response. A server that does not implement that contract is not required to reply with a protocol Pong just because the text contains the word ping.

Define what an acknowledgement means, how it identifies the outstanding heartbeat, and when an old acknowledgement is too late. Keep it separate from acknowledgement of a business operation.

A JavaScript timer also has scheduling constraints. Background tabs and busy main threads can delay callbacks. Do not interpret a missed exact timer boundary as conclusive proof that the proxy stopped forwarding.

The browser can handle protocol control frames internally, but that does not give application code a portable view of every Ping or Pong. If the page needs its own liveness decision, use an explicit application contract and a recovery policy.

A socket whose readyState is OPEN is locally considered open; it is not an independent measurement that the far application processed your last message. Use the evidence matching the question you actually need to answer.

Erthyglow kevrennek