Search code examples
javascriptnode.jspromisesocket.ioes6-promise

socket.io request information from API but wait for response before emitting data to client


I am building out an app which started as a node project. I am able to run my JS via scripts in the package.json and log stuff to the terminal.

I am now trying to plug in sockets.io to send data to the client.

I want to emit a message to the client only after my api call has finished (and I am importing this from another file).

This is my server.js

import { retrieveProjectDetails } from '../index.js';

io.on('connection', (socket) => {
  console.log('server: a user connected');

  socket.on('getProjectDetails', (data) => {
    console.log('server: getProjectDetails: ' + data);

    io.emit('sendProjectDetails', (responseData) => {
      responseData = retrieveProjectDetails(); // This is emitting before the API call has been received. 
      console.log(`server: data: ${responseData}`);
    });
  });

  socket.on('disconnect', () => {
    console.log('server: user disconnected');
  });

});

app.listen(PORT, () => console.log(`Listening on: ${PORT}`));

My client.js

const getProjectDetails = document.querySelector('.getProjectDetails');
const details = document.querySelector('.details');

getProjectDetails.addEventListener('click', (event) => {
  const target = new Date();
  socket.emit('getProjectDetails', target);
});

socket.on('sendProjectDetails', (data) => {
  details.textContent = JSON.stringify('received' + data, null, 4);
  console.log('client: sendProjectDetails was sent from the server');
  console.log(data);
});

index.js (in the root)

const getProject = () => {
  return apiRoot.get().execute();
};

// Retrieve Project information and output the result to the log
const retrieveProjectDetails = (data) => {
  getProject()
    .then(response => {
      data = response;
      console.log(data);
      return data;
    })
    .catch(console.error);
}

I am assuming I need either some callback function, or an await method (although I prefer working with promises) but as I am importing the function externally I am not sure how to wrap it using .then() or some other deferred method. Or maybe there is a way I can modify my retrieveProjectDetails function.

If you need more info (html markup, console logs etc.) just holler.

Any help is much appreciated.


Solution

  • Try returning getProject from retrieveProjectDetails, so that it returns a promise:

    const retrieveProjectDetails = (data) => {
        return getProject()
            .then(response => {
            //...
    

    and then call it first, and then emit data from the callback:

    socket.on('getProjectDetails', (data) => {
    
        console.log('server: getProjectDetails: ' + data);
    
        retrieveProjectDetails(data).then(responseData => {
    
            console.log(`server: data: ${responseData}`);
    
            io.emit('sendProjectDetails', responseData);
    
        });
    
    });