How to emit socket.io event from express controller on typescript?

I'm learning socket.io and typescript. I'm currently building an app where I want to emit event on databases changes to the client.For the backend, I'm using Express, typescript and nodeJS

I've looked on a lot of posts but I don't understand how I can access my io instance to be able to emit my event from my controller functions. Also most examples are on javascript which is more confusing.

Currently in my app.ts I have the following configuration. How can I move my addOnlineHandler, logOutHandler and sendNotificationHandler in my controller functions to be able to emit event on database change directly from createOrder function of the controller ?

I've tried importing all orderHandler function in the controller but it's not working. I'm unable to access the io instance to emit events.

app.ts

import  express  from "express";
import dotenv from "dotenv";
import userRoute from './routes/user'
import mongoose from "mongoose";
import { createServer } from "http";
import { Server,Socket } from "socket.io";
import {addOnlineShopHandler,logOutHandler, sendNotificationHandler} from "./socket/orderHandler";


dotenv.config();
const app = express();

const httpServer = createServer(app);

const io = new Server(httpServer, {
    cors:{
        origin:"*"
    }
});

const onConnection = (socket:Socket) => {
    addOnlineShopHandler(socket)
    logOutHandler(socket)
    sendNotificationHandler(socket)
    
  }

io.on("connection",onConnection)


httpServer.listen(process.env.PORT, () => {
    console.log('Backend server is running')
});

const connectToDatabase = async (dbConnectionString:string) => {
    await mongoose.connect(dbConnectionString)
    console.log('Connection to DB sucess')
}

connectToDatabase(`${process.env.MONGO_URI}`).catch(err => console.log(err))

app.use('/api/users',userRoute)

My controller file where I need to be able to emit event when order is created.

orderController.ts

import { RequestHandler } from "express";


export const createOrder:RequestHandler = async (req, res) => {
    // I want to use socket.io in this function 
    // emit event when order created 


}

My orderHandler file.

orderHandler.ts

import { Server,Socket } from "socket.io";

interface IOnlineShop {
    shopId:string, 
    socketId:string
}

let onlineShop:IOnlineShop[] = []

export const addOnlineShopHandler = (socket:Socket) => {
    console.log('someone is in')
    
    const addNewShop = (shopId:string, socketId:string) => {
        !onlineShop.some((currentShop) => currentShop.shopId === shopId) && onlineShop.push({shopId,socketId})
    }
    const newShopConnected = (shopId:string) => {
        addNewShop(shopId,socket.id)
    }

    socket.on('newShopConnected',newShopConnected)

}

export const logOutHandler = (socket:Socket) => {

    const removeShop = (socketId:string) => {
        onlineShop = onlineShop.filter((currentShop)=>{currentShop.socketId !== socketId})
        console.log('someone is out')
    }
    socket.on('disconnect',removeShop)
    
}


export const sendNotificationHandler = (socket:Socket) =>{
    const getUser = (shopId:string) =>{
        return onlineShop.find((currentShop) => currentShop.shopId === shopId)}
    const sendNotification = (data:any) =>{
        const receiver = getUser('randomshopId')
        console.log(receiver)
    }

    socket.on("sendNotif",sendNotification)
}


I've looked theses posts and still can't get around the solution, maybe using typescript is what is confusing me. Any help or explanation of the workflow would be appreciated. how to use socket.io in controller file Use socket.io in controllers Socket.IO + Express framework | Emit/Fire From Express Controller & Router

Thank you,

1 answer

  • answered 2022-01-23 02:26 ben-natan

    You can attach io to the app object:

    app.set('io', io);
    

    You can then access it from within controllers with req.app.get('io')

How many English words
do you know?
Test your English vocabulary size, and measure
how many words do you know
Online Test
Powered by Examplum