Skip to content

Instantly share code, notes, and snippets.

@vipmax
Created October 13, 2023 11:38
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save vipmax/d0205002029088a2e8c0c2f6529a572e to your computer and use it in GitHub Desktop.
Save vipmax/d0205002029088a2e8c0c2f6529a572e to your computer and use it in GitHub Desktop.
websocket send with response

websocket send with response

By default with WebSocket you only can send message.

0. Initialization

let ws = new WebSocket('ws://localhost:3000/ws')

ws.onopen = function(event) {
  console.log("on open")
}

ws.onclose = function(event) {
  console.log("on close")
}

ws.onmessage = function(event) {
  console.log("on message", event)
  let message = JSON.parse(event.data)
  // add here your logic
}

1. Default

function send(action, data) {
  ws.send(JSON.stringify({ action, data }))
  // no way to get response here
}

2. Impove
It enables you to send message and receive a response as a Promise.

// Map to associate message IDs with promises.
const promiseMap = new Map()

// Timeout duration for response.
const timeoutms = 10000 

// Improved function to send a message and wait for a response.
async function sendWithResponse(action, data) {
  return new Promise((resolve, reject) => {
    
    // Generate a unique ID for this message
    const id = Math.random().toString(36).substring(2, 15)
    // Send the message
    ws.send(JSON.stringify({ id, action, data }))
    
     // Set a timeout to reject the Promise and remove id from the map
    const timeoutId = setTimeout(() => {
      reject(new Error('timeout: no response'))
      promiseMap.delete(id)
    }, timeoutms)
    
    // Store the resolve function and timeoutId in the map
    promiseMap.set(id, { resolve, timeoutId })
  })
}

ws.onmessage = function(event) {
  console.log("on message", event)
  let message = JSON.parse(event.data)

  if (message.id && promiseMap.has(message.id)) {
    // Resolve the corresponding promise with the received message id.
    let { resolve, timeoutId } = promiseMap.get(message.id)
    clearTimeout(timeoutId)
    promiseMap.delete(message.id)
    resolve(message.data)
    return
  }
  // add here your logic
}

3. Usage

sendWithResponse("get_tree")
    .then(response => console.log(response))
    .catch(e => console.log("e", e))

sendWithResponse("get_file_content", {file: node.id})
    .then(response => console.log(response))
    .catch(e => console.log("e", e))

let response = await sendWithResponse("get_file_content", {file: node.id})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment