Joji
Joji

Reputation: 5625

React + websocket: is there a way to throttle to limit the number of times the component gets updated by websocket

I have a order book component that is getting data from this websocket endpoint "wss://ws.bitstamp.net"

The subscription is fired inside useEffect

 useEffect(() => {
    const subscribe = {
      event: "bts:subscribe",
      data: {
        channel: `order_book_${currencyPair}`
      }
    };
    const ws = new WebSocket("wss://ws.bitstamp.net");

    ws.onopen = () => {
      ws.send(JSON.stringify(subscribe));
    };
    ws.onmessage = (event) => {
      const response = JSON.parse(event.data);
      setOrders(response.data);
    };
    ws.onclose = () => {
      ws.close();
    };

    return () => {
      ws.close();
    };
  }, [currencyPair]);

But now the problem is it is updating too frequently. I would like it to update at most once every 2 seconds. I wonder how I can do that? My second question is, is there a way for me to know for a WebSocket endpoint, how often/frequently it is transmitting data to the front end? I am pretty new to WebSocket but I know it is full-duplex and the server is pushing/streaming data to the client. I am curious if there is a way to know the frequency on the frontend?

Here is the live demo https://codesandbox.io/s/orderbook-forked-r2719?file=/src/OrderBook.js

Upvotes: 0

Views: 2664

Answers (1)

n--
n--

Reputation: 3856

you can use a buffer and flush it at some interval with setInterval, like this:

  useEffect(() => {
    const subscribe = {
      event: "bts:subscribe",
      data: {
        channel: `order_book_${currencyPair}`
      }
    };
    const ws = new WebSocket("wss://ws.bitstamp.net");

    const data = new Set();
    const flush = () => {
        for (const value of data)
          setOrders(JSON.parse(value).data);
        data.clear();
    };
    let timer = setInterval(flush, 2000);

    ws.onopen = () => {
      ws.send(JSON.stringify(subscribe));
    };
    ws.onmessage = (event) => {
      data.add(event.data);
    };
    ws.onclose = () => {
      ws.close();
    };

    return () => {
      clearInterval(timer);
      ws.close();
      flush();
    };
  }, [currencyPair]);

Upvotes: 7

Related Questions