Search code examples
javascriptnode.jsweb-worker

Web worker must collect data and send it to a node js server


I am new in JS and I have a task to implement the functionality to send user click events (clicks on buttons, the email input field) to a web worker. The worker must collect data into the batches of 5 items and send it to the server (using POST /analytics/user) endpoint. The problem is that I don't understand how to collect user clicks and send them into batches of 5 items which I searched for documentation but nowhere is mentioned about batches. Could you help me please? My website has 3 buttons,2 of them doesn't have any event listeners and the last one is used to submit an email, as shown below:
enter image description here

/analytics/user endpoint code from route:

 router.post('/user', async function (req, res) {
  const payload = req.body;
  try {
    let data;
    try {
      data = await FileStorage.readJsonFile('user-analytics.json');
    } catch (e) {
      data = [];
    }

    data.push({timestamp: Date.now(), data: payload});
    await FileStorage.writeFile('user-analytics.json', data);
    await res.json({success: true})
  } catch (e) {
    console.log(e);
    res.status(500).send('Internal error');
  }
});

Let me know if I should add more information about something.

Edit :
I wrote the functions to send button clicks and after that the worker should send the data to server, but now the problem is that I can not push messages to web worker to an array ,it pushes only first message..

Function for sending user clicks to the web worker :

  export const sendUserClicksToWorker = () => {
    const allButtonsToStore = document.getElementsByClassName("app-section__button");
    const inputField = document.getElementsByClassName("form-input")
    let reason = [];
    //for loop for pushing clicks from buttonts to the array
    for (let x = 0; x < allButtonsToStore.length; x++) {
        allButtonsToStore[x].addEventListener("click", function () {
            worker.postMessage(this.textContent)
            console.log(this.textContent)
        });
    }
    //for loop for pushing click from email input field to the array
    for (let x = 0; x < inputField.length; x++) {
        inputField[x].addEventListener("click", function () {
            worker.postMessage(this.textContent)
            console.log(this.textContent)
        });
    }
    
}

Function for sending data to the server :

export const sendButtonClicksToServer = (dataToSend) => {
    sendHttpRequest('POST', 'http://localhost:8080/analytics/user', {
        dataToSend
    }).then(responseData => {
        return responseData
        //console.log(responseData);
    }).catch(err => {
        console.log(err, err.data)
        window.alert(err.data.error)
    })
}

And in main js file :

 if (window.Worker) {
      const url = new URL('./scripts/worker.js', import.meta.url);
      const worker = new Worker(url);
      
      const allButtonsToStore = document.getElementsByClassName("app-section__button");
      const inputField = document.getElementsByClassName("form-input")
      //for loop for pushing clicks from buttonts to the array
      for (let x = 0; x < allButtonsToStore.length; x++) {
          allButtonsToStore[x].addEventListener("click", function () {
              worker.postMessage(this.textContent)
              //console.log(this.textContent)
          });
      }
      //for loop for pushing click from email input field to the array
      for (let x = 0; x < inputField.length; x++) {
          inputField[x].addEventListener("click", function () {
              worker.postMessage(this.textContent)
             // console.log(this.textContent)
          });
      }

      worker.onmessage = e => {
        console.log(e.data)
        sendButtonClicksToServer(e.data);
      }
      worker.onerror = error => {
        console.log(error.message)
      }
    }

And worker.js :

let data = []
onmessage = function (e) {
    console.log('Data Received: ',e.data)

let receivedButtonClicks = e.data
// data.push(receivedButtonClicks)
// if (data.length > 4) {
//     postMessage(data)
//     data.length = 0;
//     console.log('Data received!')
//     console.log(data)
// }
for ( let i = 0 ; i< 5;i++){
    data[i].push(receivedButtonClicks)
}



console.log('blabla',data)
}

Now I don't understand 100% where is the problem and how to fix it??..


Solution

  • So,i managed how to do this task and i came back here showing my functionality :

    I did two functions,one for sending user clicks to the webworker in the following way :

    const sendUserClicksToWorker = () => {
        if (window.Worker) {
            const url = new URL('./worker.js', import.meta.url);
            const worker = new Worker(url);
    
            const allButtonsToStore = document.getElementsByClassName("app-section__button");
            const inputField = document.getElementsByClassName("form-input")
    
            //for loop for pushing clicks from buttonts to the array
            for (let x = 0; x < allButtonsToStore.length; x++) {
                allButtonsToStore[x].addEventListener("click", function () {
                    worker.postMessage(this.textContent)
                });
            }
            //for loop for pushing click from email input field to the array
            for (let x = 0; x < inputField.length; x++) {
                inputField[x].addEventListener("click", function () {
                    worker.postMessage(this.textContent)
                });
            }
    
            worker.onmessage = e => {
               // console.log('Thread received data: ', e.data)
                sendButtonClicksToServer(e.data);
            }
            worker.onerror = error => {
                console.log(error.message)
            }
        }
    
    }
    

    On every button click it posts a message to the webworker. And the second function for sending data to the server:

    const sendButtonClicksToServer = (dataToSend) => {
        sendHttpRequest('POST', 'http://localhost:8080/analytics/user', {
            dataToSend
        }).then(responseData => {
            return responseData
        }).catch(err => {
            console.log(err, err.data)
            window.alert(err.data.error)
        })
    }
    

    The webworker procces the data received this way and sends back to the main thread were on next step,it is being send to the server:

    let batch = []
    onmessage = function (e) {
        console.log('Data Received: ',e.data)
        let receivedButtonClicks = e.data
    
    for ( let i = 0 ; i< 1;i++){
        batch.push(receivedButtonClicks)
    
        if (batch.length > 4){
            postMessage(batch)
            batch.length = 0
            console.log('Data was sent!')
        }
    }
    
    }
    

    It wasnt that hard,but it took damn too much time. Thanks everyone for help!