Есть ли способ завершить и перезапустить новое подключение к веб-сокету при замене реквизита? - PullRequest
0 голосов
/ 26 октября 2019

Мне удалось установить соединение с веб-сокетом, используя URL-адрес, передаваемый в качестве реквизита из App.js в дочерний компонент. При изменении значения реквизита я хочу, чтобы уже установленное соединение веб-сокета было прервано, и новое соединение было установлено с передачей нового значения реквизита.

Дочерний компонент инициирует соединение в момент его монтирования.

export class Stream extends Component {
  state = {
ws: null
//url: this.props.value
  };

  componentDidMount() {
this.connect();
  }

  componentDidUpdate(prevProps) {
if (this.props.value !== prevProps.value) {
  this.disconnect(prevProps);
  //this.connect(this.props.value);
}
  }

  componentWillUnmount() {
//socket.close();
  }

  connect = () => {
var socket = new WebSocket("wss://ws.dummy.net/");
let that = this; // cache the this
var subscribeMsg = {
  event: "subscribe",
  data: {
    channel: "order" + this.props.value
  }
};

function serializeData(data) {
  //console.log(data);
  that.setState({
    ws: data //Map the serialized data to the state
  });
}

// websocket onopen event listener
socket.onopen = () => {
  socket.send(JSON.stringify(subscribeMsg));
  console.log("connected websocket main component");
};

socket.onmessage = function(evt) {
  var response = JSON.parse(evt.data);
  console.log(response);
  /**
   * This switch statement handles message logic. It processes data in case of data event
   * and it reconnects if the server requires.
   */
  switch (response.event) {
    case "data": {
      serializeData(response.data);
      break;
    }
    default: {
      //console.log("Error in case assignment");
      break;
    }
  }
};
// websocket onclose event listener
socket.onclose = e => {
  console.log("Socket is closed");
};

// websocket onerror event listener
socket.onerror = err => {
  console.error(
    "Socket encountered error: ",
    err.message,
    "Closing socket"
  );
};
  };

  disconnect = prevProps => {
var socket = new WebSocket("wss://ws.dummy.net/");
var unsubscribeMsg = {
  event: "unsubscribe",
  data: {
    channel: "order" + prevProps.value
  }
    };

socket.close();
socket.onclose = e => {
  socket.send(JSON.stringify(unsubscribeMsg));
  console.log("DISCONNECT Socket is closed");
};
  };
}

1 Ответ

0 голосов
/ 04 ноября 2019

Невозможно передавать данные по закрытому соединению, как это сделано в socket.onclose обработчике события в методе disconnect компонента.

Я предлагаю извлечь все, что связано с созданием сокета и регистрацией событияобработчик функции. Например,

/**
 * Creates a websocket and registers its handlers
 * @param onMessageCb
 * @param uri
 * @param value 
 */
function createWebSocket(onMessageCb, uri, value) {

    const socket = new WebSocket(uri);

    const subscribeMsg = {
        event: "subscribe",
        data: {
            channel: "order" + value
        }
    };

    const unsubscribeMsg = {
        event: "unsubscribe",
        data: {
            channel: "order" + value
        }
    };

    // websocket onopen event listener
    socket.onopen = () => {
        socket.send(JSON.stringify(subscribeMsg));
        console.log("connected websocket main component");
    };

    socket.onmessage = function (evt) {
        var response = JSON.parse(evt.data);
        console.log(response);
        /**
         * This switch statement handles message logic. It processes data in case of data event
         * and it reconnects if the server requires.
         */
        switch (response.event) {
            case "data": {
                onMessageCb(response.data);
                break;
            }
            default: {
                //console.log("Error in case assignment");
                break;
            }
        }
    };

    // websocket onclose event listener
    socket.onclose = e => {
        console.log("Socket is closed");
    };

    // websocket onerror event listener
    socket.onerror = err => {
        console.error(
            "Socket encountered error: ",
            err.message,
            "Closing socket"
        );
    };

    function close() {
        socket.send(JSON.stringify(unsubscribeMsg));
        socket.close();
    }

    return {
        send: socket.send,
        close
    };
}

Затем создайте сокет с помощью этой функции и задайте свойство сокета для экземпляра компонента.

export class Stream extends Component {
    state = {
        ws: null
        //url: this.props.value
    };

    socket = null;

    setWs = (data) => {
        this.setState({
            ws: data //Map the serialized data to the state
        });
    }

    componentDidMount() {
        this.socket = createWebSocket(this.setWs, this.props.url, this.props.value);
    }

    componentDidUpdate(prevProps) {
        if (this.props.value !== prevProps.value) {
            this.socket.close();
            this.socket = createWebSocket(this.setWs, this.props.url, this.props.value);
        }
    }

    componentWillUnmount() {
        this.socket.close();
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...