Как правильно обмениваться данными по протоколу WebSocket?

Как наилучшим образом взаимодействовать с сервером, отправляя данные, ожидая ответа, возвращая его из метода и продолжая выполнение кода?
  • 16 мая 2024 г. 13:00
Ответы на вопрос 2
Для обмена данными по протоколу WebSocket, можно использовать WebSocket API браузера или WebSocket библиотеки на сервере (например, ws в Node.js). 

Для отправки данных на сервер, ожидания ответа и возврата его из метода можно использовать асинхронные функции и обработчики событий. Вот пример кода на JavaScript, использующий WebSocket API браузера:

```javascript
const socket = new WebSocket('ws://example.com');

function sendData(data) {
  return new Promise((resolve, reject) => {
    socket.onmessage = function(event) {
      resolve(event.data);
    };

    socket.onerror = function(event) {
      reject(event);
    };

    socket.send(JSON.stringify(data));
  });
}

async function interactionWithServer() {
  try {
    const response = await sendData({message: 'Hello server'});
    console.log('Received response from server:', response);
    // продолжаем выполнение кода
  } catch (error) {
    console.error('Error occurred:', error);
  }
}

interactionWithServer();
```

В данном примере мы создаем новый WebSocket объект, отправляем данные на сервер с использованием метода `send()`, ожидаем ответ с помощью обработчика события `onmessage` и возвращаем его с помощью `Promise`. Далее, используя асинхронные функции и ключевое слово `await`, мы отправляем данные на сервер, ожидаем ответ, выводим его в консоль и продолжаем выполнение кода.

Это лишь один из возможных способов взаимодействия с сервером по протоколу WebSocket. В зависимости от задачи и используемой технологии можно использовать различные подходы.
Я сделал так: протокол взял json rpc : 

let requestCounter = 0
let jsonRpcPromises = {}
function jsonrpc (method, params) {
  const dataToSend = { jsonrpc: '2.0', method, params, id: ++requestCounter }
  socket.send(JSON.stringify(dataToSend))
  return new Promise((resolve, reject) => {
    jsonRpcPromises[requestCounter] = { resolve, reject }
  })
}

function completeJsonrpc (message) {
  const { id, error, result } = message
  if (error !== undefined) {
    jsonRpcPromises[id]?.reject(error)
  } else {
    jsonRpcPromises[id]?.resolve(result)
  }
  delete (jsonRpcPromises[id])
}

//
    socket.onmessage = function (event) {
      const message = JSON.parse(event.data)
///
      if (message.jsonrpc) {
        completeJsonrpc(message)
      } else if (...) {
/// 
    }


Код выше намерено упрощен, в нем нет обработок крайних случаев (типа обрыва связи, реконнекта с продолжением или без продолжения обработки, кривых id и т.п.)

сам протокол упрощен, нет пакетного режима, передача идет по одному сообщению, а не массивами (потому что с сокетом это не нужно)
Похожие вопросы